├── .gitignore
├── AndroidProjects.iml
├── ChangeLog.md
├── HeartBeat.iml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── app.iml
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── maxiee
│ │ └── heartbeat
│ │ └── ApplicationTest.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ ├── donate_list.html
│ ├── label_event_thought.html
│ ├── licenses.html
│ └── what_heartbeat_is.html
│ ├── java
│ └── com
│ │ └── maxiee
│ │ └── heartbeat
│ │ ├── HeartBeatApplication.java
│ │ ├── backup
│ │ ├── BackupAllTask.java
│ │ ├── BackupManager.java
│ │ ├── FileDES.java
│ │ └── RestoreAllTask.java
│ │ ├── common
│ │ ├── DialogAsyncTask.java
│ │ ├── FileUtils.java
│ │ ├── FixedHeightScrollingViewBehavior.java
│ │ ├── GalleryUtils.java
│ │ ├── ThemeUtils.java
│ │ ├── TimeUtils.java
│ │ ├── cloudview
│ │ │ ├── Cloud.java
│ │ │ ├── CloudTag.java
│ │ │ └── CloudView.java
│ │ └── tagview
│ │ │ ├── Constants.java
│ │ │ ├── Tag.java
│ │ │ └── TagView.java
│ │ ├── data
│ │ ├── BaseEventManager.java
│ │ ├── DataManager.java
│ │ ├── EventManager.java
│ │ └── TodayManager.java
│ │ ├── database
│ │ ├── DatabaseHelper.java
│ │ ├── api
│ │ │ ├── AddCrashApi.java
│ │ │ ├── BaseDBApi.java
│ │ │ ├── GetAllCrashesApi.java
│ │ │ ├── GetCountByNameApi.java
│ │ │ ├── GetCountSpecDayApi.java
│ │ │ └── ImageUriUpgradeApi.java
│ │ ├── tables
│ │ │ ├── CrashTable.java
│ │ │ ├── EventImageRelationTable.java
│ │ │ ├── EventLabelRelationTable.java
│ │ │ ├── EventThoughtRelationTable.java
│ │ │ ├── EventsTable.java
│ │ │ ├── ImageTable.java
│ │ │ ├── LabelsTable.java
│ │ │ ├── ThoughtResTable.java
│ │ │ └── ThoughtsTable.java
│ │ └── utils
│ │ │ ├── DatabaseUtils.java
│ │ │ ├── EventUtils.java
│ │ │ ├── ImageUtils.java
│ │ │ ├── LabelUtils.java
│ │ │ └── ThoughtUtils.java
│ │ ├── model
│ │ ├── Crash.java
│ │ ├── DayCard.java
│ │ ├── Event.java
│ │ ├── Image.java
│ │ ├── Label.java
│ │ ├── ThoughtRes.java
│ │ └── Thoughts.java
│ │ ├── provider
│ │ ├── Constant.java
│ │ ├── HeartBeatContentProvider.java
│ │ ├── IProviderEventDelegate.java
│ │ ├── IProviderThoughtDelegate.java
│ │ ├── ProviderEventDelegate.java
│ │ └── ProviderThoughtDelegete.java
│ │ ├── support
│ │ ├── CrashHandler.java
│ │ └── StopWatch.java
│ │ ├── ui
│ │ ├── AddEditThoughtActivity.java
│ │ ├── AddEventActivity.java
│ │ ├── CrashDetailActivity.java
│ │ ├── CrashListActivity.java
│ │ ├── EntryActivity.java
│ │ ├── EventDetailActivity.java
│ │ ├── GalleryActivity.java
│ │ ├── HelpCenterActivity.java
│ │ ├── HelpCenterDetailActivity.java
│ │ ├── LabelDetailActivity.java
│ │ ├── MainActivity.java
│ │ ├── PatternActivity.java
│ │ ├── SearchResultActivity.java
│ │ ├── SettingsActivity.java
│ │ ├── adapter
│ │ │ ├── CrashListAdapter.java
│ │ │ ├── DayCardEventAdapter.java
│ │ │ ├── EventListAdapter.java
│ │ │ ├── HelpListAdapter.java
│ │ │ ├── ThoughtTimeaxisAdapter.java
│ │ │ └── TodayEventAdapter.java
│ │ ├── common
│ │ │ ├── BaseActivity.java
│ │ │ ├── HintSearchBox.java
│ │ │ ├── RecyclerInsetsDecoration.java
│ │ │ ├── ScrollingFABBehavior.java
│ │ │ └── mdheaderview
│ │ │ │ ├── MDHeaderView.java
│ │ │ │ └── TriView.java
│ │ └── fragments
│ │ │ ├── EventListFragment.java
│ │ │ ├── EventTodayFragment.java
│ │ │ ├── LabelCloudFragment.java
│ │ │ ├── SettingsFragment.java
│ │ │ └── StatisticsFragment.java
│ │ └── widget
│ │ └── HeartBeatWidgetProvider.java
│ └── res
│ ├── drawable-hdpi
│ ├── ic_action_add.png
│ ├── ic_action_content_copy.png
│ ├── ic_action_dashboard.png
│ ├── ic_action_done.png
│ ├── ic_action_label.png
│ ├── ic_action_list.png
│ ├── ic_action_messenger.png
│ ├── ic_action_photo.png
│ ├── ic_action_reorder.png
│ ├── ic_action_search.png
│ ├── ic_action_share.png
│ ├── ic_action_theaters.png
│ ├── ic_action_today.png
│ └── ic_action_trending_up.png
│ ├── drawable-mdpi
│ ├── ic_action_add.png
│ ├── ic_action_content_copy.png
│ ├── ic_action_dashboard.png
│ ├── ic_action_done.png
│ ├── ic_action_label.png
│ ├── ic_action_list.png
│ ├── ic_action_messenger.png
│ ├── ic_action_photo.png
│ ├── ic_action_reorder.png
│ ├── ic_action_search.png
│ ├── ic_action_share.png
│ ├── ic_action_theaters.png
│ ├── ic_action_today.png
│ └── ic_action_trending_up.png
│ ├── drawable-xhdpi
│ ├── ic_action_add.png
│ ├── ic_action_content_copy.png
│ ├── ic_action_dashboard.png
│ ├── ic_action_done.png
│ ├── ic_action_label.png
│ ├── ic_action_list.png
│ ├── ic_action_messenger.png
│ ├── ic_action_photo.png
│ ├── ic_action_reorder.png
│ ├── ic_action_search.png
│ ├── ic_action_share.png
│ ├── ic_action_theaters.png
│ ├── ic_action_today.png
│ └── ic_action_trending_up.png
│ ├── drawable-xxhdpi
│ ├── ic_action_add.png
│ ├── ic_action_content_copy.png
│ ├── ic_action_dashboard.png
│ ├── ic_action_done.png
│ ├── ic_action_label.png
│ ├── ic_action_list.png
│ ├── ic_action_messenger.png
│ ├── ic_action_photo.png
│ ├── ic_action_reorder.png
│ ├── ic_action_search.png
│ ├── ic_action_share.png
│ ├── ic_action_theaters.png
│ ├── ic_action_today.png
│ └── ic_action_trending_up.png
│ ├── drawable-xxxhdpi
│ ├── ic_action_add.png
│ ├── ic_action_content_copy.png
│ ├── ic_action_dashboard.png
│ ├── ic_action_done.png
│ ├── ic_action_label.png
│ ├── ic_action_list.png
│ ├── ic_action_messenger.png
│ ├── ic_action_photo.png
│ ├── ic_action_reorder.png
│ ├── ic_action_search.png
│ ├── ic_action_share.png
│ ├── ic_action_theaters.png
│ ├── ic_action_today.png
│ └── ic_action_trending_up.png
│ ├── drawable
│ ├── card.xml
│ ├── circle_timeaxis.xml
│ ├── empty_bg.png
│ ├── empty_bg1.png
│ └── empty_bg2.png
│ ├── layout
│ ├── activity_add_edit_thought.xml
│ ├── activity_add_event.xml
│ ├── activity_crash_detail.xml
│ ├── activity_crash_list.xml
│ ├── activity_entry.xml
│ ├── activity_event_detail.xml
│ ├── activity_gallery.xml
│ ├── activity_help_center.xml
│ ├── activity_help_center_detail.xml
│ ├── activity_label_detail.xml
│ ├── activity_main.xml
│ ├── activity_pattern.xml
│ ├── activity_search_result.xml
│ ├── activity_settings.xml
│ ├── dialog_edit_event.xml
│ ├── dialog_edit_thought.xml
│ ├── dialog_new_label.xml
│ ├── dialog_new_thought.xml
│ ├── fragment_event_list.xml
│ ├── fragment_event_today.xml
│ ├── fragment_label_cloud.xml
│ ├── fragment_statistics.xml
│ ├── include_activity_main.xml
│ ├── item_crash_card.xml
│ ├── item_day_card.xml
│ ├── item_day_card_item.xml
│ ├── item_event_card.xml
│ ├── item_help_center.xml
│ ├── item_thought_timeaxis.xml
│ ├── item_today_header.xml
│ ├── tagview_item.xml
│ ├── toolbar.xml
│ └── widget.xml
│ ├── menu
│ ├── dialog_edit_thought.xml
│ ├── dialog_new_thought.xml
│ ├── drawer_view.xml
│ ├── fragment_eventlist_type.xml
│ ├── menu_crash_detail.xml
│ ├── menu_event_detail.xml
│ └── menu_main.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ ├── values-v21
│ └── styles.xml
│ ├── values-w820dp
│ └── dimens.xml
│ ├── values-zh
│ └── strings.xml
│ ├── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ ├── styles.xml
│ └── tagview_attr.xml
│ └── xml
│ ├── settings.xml
│ └── widget_info.xml
├── attitude.iml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── icon.png
├── multi-image-selector
├── .gitignore
├── build.gradle
├── multi-image-selector.iml
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── me
│ │ └── nereo
│ │ └── multi_image_selector
│ │ └── ApplicationTest.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── me
│ │ └── nereo
│ │ └── multi_image_selector
│ │ ├── MultiImageSelectorActivity.java
│ │ ├── MultiImageSelectorFragment.java
│ │ ├── adapter
│ │ ├── FolderAdapter.java
│ │ └── ImageGridAdapter.java
│ │ ├── bean
│ │ ├── Folder.java
│ │ └── Image.java
│ │ ├── utils
│ │ ├── FileUtils.java
│ │ ├── ScreenUtils.java
│ │ └── TimeUtils.java
│ │ └── view
│ │ ├── SquareFrameLayout.java
│ │ └── SquaredImageView.java
│ └── res
│ ├── color
│ ├── default_text_color.xml
│ └── folder_text_color.xml
│ ├── drawable-xhdpi
│ ├── btn_back.png
│ ├── default_check_s.png
│ ├── ic_menu_back.png
│ └── selector_indicator.png
│ ├── drawable-xxhdpi
│ ├── asv.png
│ ├── asy.png
│ ├── btn_selected.png
│ ├── btn_unselected.png
│ ├── default_check.png
│ ├── default_error.png
│ └── text_indicator.png
│ ├── drawable
│ └── action_btn.xml
│ ├── layout-v14
│ └── fragment_multi_image.xml
│ ├── layout
│ ├── activity_default.xml
│ ├── cmp_customer_actionbar.xml
│ ├── fragment_multi_image.xml
│ ├── list_item_camera.xml
│ ├── list_item_folder.xml
│ └── list_item_image.xml
│ ├── values-sw360dp
│ └── dimens.xml
│ ├── values-sw480dp
│ └── dimens.xml
│ ├── values-sw720dp
│ └── dimens.xml
│ ├── values-zh
│ └── strings.xml
│ └── values
│ ├── dimens.xml
│ └── strings.xml
├── screenshot.png
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Gradle files
16 | .gradle/
17 | build/
18 | /*/build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | .gradle
30 | /local.properties
31 | /.idea/workspace.xml
32 | /.idea/libraries
33 | .DS_Store
34 | /build
35 | /captures
36 |
--------------------------------------------------------------------------------
/AndroidProjects.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/HeartBeat.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion '23.0.2'
6 |
7 | defaultConfig {
8 | applicationId "com.maxiee.heartbeat"
9 | minSdkVersion 15
10 | targetSdkVersion 23
11 | versionCode 29
12 | versionName "0.9.5"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | repositories {
23 | mavenCentral()
24 | maven { url "https://jitpack.io" }
25 | maven { url "https://oss.sonatype.org/content/repositories/snapshots"}
26 | }
27 |
28 | dependencies {
29 | compile fileTree(include: ['*.jar'], dir: 'libs')
30 | compile 'com.github.bumptech.glide:glide:3.6.1'
31 | compile 'com.github.PhilJay:MPAndroidChart:v2.1.0'
32 | compile 'com.quinny898.library.persistentsearch:library:1.1.0-SNAPSHOT'
33 | compile 'com.eftimoff:android-patternview:1.0.2@aar'
34 | compile 'com.android.support:appcompat-v7:23.1.1'
35 | compile 'com.android.support:design:23.1.1'
36 | compile 'com.android.support:cardview-v7:23.1.1'
37 | compile 'com.android.support:recyclerview-v7:23.1.1'
38 | compile 'com.commit451:PhotoView:1.2.4'
39 | compile 'com.jakewharton:butterknife:7.0.1'
40 | compile 'com.wdullaer:materialdatetimepicker:2.1.0'
41 | compile project(':multi-image-selector')
42 | debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta2'
43 | releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
44 | testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
45 | }
46 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /home/maxiee/Android/Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/maxiee/heartbeat/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/HeartBeatApplication.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat;
2 |
3 | import android.app.Application;
4 |
5 | import com.squareup.leakcanary.LeakCanary;
6 |
7 | /**
8 | * Created by maxiee on 16/4/18.
9 | */
10 | public class HeartBeatApplication extends Application {
11 |
12 | @Override
13 | public void onCreate() {
14 | super.onCreate();
15 | LeakCanary.install(this);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/backup/BackupAllTask.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.backup;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.Context;
5 | import android.os.AsyncTask;
6 | import android.widget.Toast;
7 |
8 | import com.maxiee.heartbeat.R;
9 |
10 | /**
11 | * Created by maxiee on 16/4/21.
12 | */
13 | public class BackupAllTask extends AsyncTask {
14 | private Context mContext;
15 | ProgressDialog mProgressDialog;
16 |
17 | public BackupAllTask(Context context) {
18 | mContext = context;
19 | }
20 |
21 | @Override
22 | protected void onPreExecute() {
23 | mProgressDialog = new ProgressDialog(mContext);
24 | mProgressDialog.setMessage(mContext.getString(R.string.backuping));
25 | mProgressDialog.setCancelable(false);
26 | mProgressDialog.show();
27 | }
28 |
29 | @Override
30 | protected String doInBackground(Void... params) {
31 | return BackupManager.backupAll(mContext);
32 | }
33 |
34 | @Override
35 | protected void onPostExecute(String ret) {
36 | mProgressDialog.cancel();
37 | if (ret != null) {
38 | Toast.makeText(
39 | mContext, mContext.getString(R.string.backup_ok),
40 | Toast.LENGTH_LONG).show();
41 | } else {
42 | Toast.makeText(
43 | mContext, mContext.getString(R.string.backup_failed),
44 | Toast.LENGTH_LONG).show();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/backup/FileDES.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.backup;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.FileOutputStream;
6 | import java.io.InputStream;
7 | import java.io.OutputStream;
8 | import java.security.Key;
9 |
10 | import javax.crypto.Cipher;
11 | import javax.crypto.CipherInputStream;
12 | import javax.crypto.spec.SecretKeySpec;
13 |
14 | /**
15 | * Created by maxiee on 15-8-12.
16 | */
17 | public class FileDES {
18 | private final static String KEY_RULE = "maxieejudy";
19 |
20 | private static Key initKey() {
21 | byte[] keyByte = KEY_RULE.getBytes();
22 | byte[] byteTemp = new byte[8];
23 | for (int i=0; i 0) {
40 | os.write(buffer, 0, len);
41 | os.flush();
42 | }
43 | os.close();
44 | cin.close();
45 | is.close();
46 | } catch (Exception e) {e.printStackTrace();}
47 | }
48 |
49 | public static boolean doDecryptFile (InputStream in, OutputStream os) throws Exception{
50 | if (in == null) return false;
51 | Cipher decryptCipher = Cipher.getInstance("DES");
52 | decryptCipher.init(Cipher.DECRYPT_MODE, initKey());
53 | CipherInputStream cin = new CipherInputStream(in, decryptCipher);
54 | byte[] buffer = new byte[1024];
55 | int len;
56 | while ((len=cin.read(buffer)) > 0) {
57 | os.write(buffer, 0, len);
58 | }
59 | cin.close();
60 | return true;
61 | }
62 |
63 | public static boolean doDecryptFileNotClose (InputStream in, OutputStream os) throws Exception{
64 | if (in == null) return false;
65 | Cipher decryptCipher = Cipher.getInstance("DES");
66 | decryptCipher.init(Cipher.DECRYPT_MODE, initKey());
67 | CipherInputStream cin = new CipherInputStream(in, decryptCipher);
68 | byte[] buffer = new byte[1024];
69 | int len;
70 | while ((len=cin.read(buffer)) > 0) {
71 | os.write(buffer, 0, len);
72 | }
73 | return true;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/backup/RestoreAllTask.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.backup;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.AsyncTask;
7 | import android.widget.Toast;
8 |
9 | import com.maxiee.heartbeat.R;
10 |
11 | /**
12 | * Created by maxiee on 16/4/21.
13 | */
14 | public class RestoreAllTask extends AsyncTask{
15 | private Context mContext;
16 | ProgressDialog mProgressDialog;
17 |
18 | public RestoreAllTask(Context context) {
19 | mContext = context;
20 | }
21 |
22 | @Override
23 | protected void onPreExecute() {
24 | mProgressDialog = new ProgressDialog(mContext);
25 | mProgressDialog.setMessage(mContext.getString(R.string.restoring));
26 | mProgressDialog.setCancelable(false);
27 | mProgressDialog.show();
28 | }
29 |
30 | @Override
31 | protected String doInBackground(Intent... params) {
32 | return BackupManager.restoreAll(mContext, params[0]);
33 | }
34 |
35 | @Override
36 | protected void onPostExecute(String s) {
37 | mProgressDialog.cancel();
38 | Toast.makeText(mContext, s, Toast.LENGTH_LONG).show();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/common/DialogAsyncTask.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.common;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.os.AsyncTask;
7 | import android.support.v7.app.AlertDialog;
8 |
9 |
10 | /**
11 | * Created by maxiee on 15-5-17.
12 | */
13 | public abstract class DialogAsyncTask extends AsyncTask{
14 |
15 | private ProgressDialog progressDialog;
16 | private Context mContext;
17 | protected boolean mTaskSuccess = false;
18 |
19 | public DialogAsyncTask(Context context) {
20 | mContext = context;
21 | }
22 |
23 | @Override
24 | protected void onPreExecute() {
25 | super.onPreExecute();
26 | progressDialog = new ProgressDialog(mContext);
27 | progressDialog.setMessage("正在提交");
28 | progressDialog.setCancelable(false);
29 | progressDialog.show();
30 | }
31 |
32 | @Override
33 | protected void onPostExecute(String msg) {
34 | super.onPostExecute(msg);
35 | progressDialog.dismiss();
36 |
37 | if (mTaskSuccess) {
38 | showSuccessDialog(msg);
39 | } else {
40 | showFailedDialog(msg);
41 | }
42 | }
43 |
44 | private void showSuccessDialog(String msg) {
45 | new AlertDialog.Builder(mContext)
46 | .setMessage(msg)
47 | .setCancelable(false)
48 | .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
49 | @Override
50 | public void onClick(DialogInterface dialog, int id) {
51 | dialog.dismiss();
52 | onFinish();
53 | }
54 | })
55 | .create()
56 | .show();
57 | }
58 |
59 | private void showFailedDialog(String msg) {
60 | new AlertDialog.Builder(mContext)
61 | .setMessage(msg)
62 | .setCancelable(true)
63 | .setNegativeButton(android.R.string.cancel, null)
64 | .create()
65 | .show();
66 | }
67 |
68 | public Context getmContext() {
69 | return mContext;
70 | }
71 |
72 | public abstract void onFinish();
73 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/common/FixedHeightScrollingViewBehavior.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.common;
2 |
3 | /**
4 | * Created by maxiee on 15-6-13.
5 | *
6 | * The cheesesquare project has a bug:
7 | * in layouts using CoordinatorLayout, when there is only one CardView,
8 | * it will display incorrectly.
9 | *
10 | * This class is copy by EmmanuelVinas's Gist which will fix this problem.
11 | * how-to use:
12 | * app:layout_behavior="com.maxiee.attitude.common.FixedHeightScrollingViewBehavior"
13 | */
14 | import android.content.Context;
15 | import android.support.design.widget.AppBarLayout;
16 | import android.support.design.widget.CoordinatorLayout;
17 | import android.support.v4.view.ViewCompat;
18 | import android.util.AttributeSet;
19 | import android.view.View;
20 |
21 | import java.util.List;
22 |
23 | public class FixedHeightScrollingViewBehavior extends AppBarLayout.ScrollingViewBehavior{
24 |
25 | public FixedHeightScrollingViewBehavior() {
26 | }
27 |
28 | public FixedHeightScrollingViewBehavior(Context context, AttributeSet attrs) {
29 | super(context, attrs);
30 | }
31 |
32 | public boolean onMeasureChild(CoordinatorLayout parent, View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
33 | if(child.getLayoutParams().height == -1) {
34 | List dependencies = parent.getDependencies(child);
35 | if(dependencies.isEmpty()) {
36 | return false;
37 | }
38 |
39 | AppBarLayout appBar = findFirstAppBarLayout(dependencies);
40 | if(appBar != null && ViewCompat.isLaidOut(appBar)) {
41 | if(ViewCompat.getFitsSystemWindows(appBar)) {
42 | ViewCompat.setFitsSystemWindows(child, true);
43 | }
44 |
45 | int scrollRange = appBar.getTotalScrollRange();
46 | int height = parent.getHeight() - appBar.getMeasuredHeight() + Math.min(scrollRange, parent.getHeight()- heightUsed);
47 | int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
48 | parent.onMeasureChild(child, parentWidthMeasureSpec, widthUsed, heightMeasureSpec, heightUsed);
49 | return true;
50 | }
51 | }
52 |
53 | return false;
54 | }
55 |
56 | private static AppBarLayout findFirstAppBarLayout(List views) {
57 | int i = 0;
58 |
59 | for(int z = views.size(); i < z; ++i) {
60 | View view = (View)views.get(i);
61 | if(view instanceof AppBarLayout) {
62 | return (AppBarLayout)view;
63 | }
64 | }
65 |
66 | return null;
67 | }
68 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/common/cloudview/Cloud.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.common.cloudview;
2 |
3 | import java.util.Collection;
4 | import java.util.HashMap;
5 | import java.util.Iterator;
6 | import java.util.LinkedList;
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | /**
11 | * Created by maxiee on 15-6-24.
12 | *
13 | * Modified from: luixal/android-tagcloud
14 | * https://github.com/luixal/android-tagcloud
15 | *
16 | */
17 | public class Cloud {
18 |
19 | public enum Rounding {
20 | CEIL,
21 | FLOOR,
22 | ROUND
23 | }
24 |
25 | private Map cloud = new HashMap<>();
26 |
27 | private double minWeight = 0.0;
28 | private double maxWeight = 4.0;
29 |
30 | private int maxTagToDisplay = 50;
31 |
32 | /* tags having score under the threshold are excluded. */
33 | private double threshold = 0.0;
34 |
35 | /* tags' timestamp older than tagLifetime are excluded. */
36 | private long tagLifetime = -1;
37 |
38 | private Rounding rounding = Rounding.CEIL;
39 |
40 | public Cloud() {}
41 |
42 | public void addTag(CloudTag tag) {
43 | if (tag == null) {
44 | return;
45 | }
46 |
47 | String key = tag.getName();
48 | if (cloud.containsKey(key)) {
49 | tag.addScore(cloud.get(key).getScore());
50 | }
51 |
52 | cloud.put(key, tag);
53 | }
54 |
55 | public void addTags(Collection tags) {
56 | if (tags == null) {
57 | return;
58 | }
59 |
60 | Iterator it = tags.iterator();
61 | while (it.hasNext()) {
62 | addTag(it.next());
63 | }
64 | }
65 |
66 | protected List getOutputTags() {
67 | List emptyList = new LinkedList<>();
68 |
69 | if (getCloud() == null) {
70 | return emptyList;
71 | }
72 |
73 | List result = new LinkedList<>();
74 | Iterator it = getCloud().values().iterator();
75 | CloudTag tag;
76 |
77 | double max = 0.0;
78 |
79 | while (it.hasNext()) {
80 | tag = it.next();
81 |
82 | // if (tag.getScore() < threshold ||
83 | // tag.getTimestamp() < tagLifetime) {
84 | // continue;
85 | // }
86 |
87 | result.add(tag);
88 |
89 | if (tag.getScore() > max) {
90 | max = tag.getScore();
91 | }
92 | }
93 |
94 | return result;
95 | }
96 |
97 | protected Map getCloud() {
98 | return cloud;
99 | }
100 |
101 | public void setMaxWeight(double maxWeight) {
102 | this.maxWeight = maxWeight;
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/common/cloudview/CloudTag.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.common.cloudview;
2 |
3 | /**
4 | * Created by maxiee on 15-6-24.
5 | */
6 | public class CloudTag {
7 |
8 | private String name;
9 | private double score = 1.0;
10 | private double normScore = 0.0;
11 | private double weight = 10.0;
12 | private long timestamp;
13 |
14 | public CloudTag() {}
15 |
16 | public CloudTag(String name) {
17 | this.name = name;
18 | }
19 |
20 | public CloudTag(String name, int score) {
21 | this.name = name;
22 | this.score = score;
23 | }
24 |
25 | public double getScore() {
26 | return score;
27 | }
28 |
29 | public long getTimestamp() {
30 | return timestamp;
31 | }
32 |
33 | public String getName() {
34 | return name;
35 | }
36 |
37 | public int getWeightInt() {
38 | return (int) Math.ceil(score * weight);
39 | }
40 |
41 | public void setWeight(double weight) {
42 | this.weight = weight;
43 | }
44 |
45 | public void addScore(double val) {
46 | score += val;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/common/tagview/Constants.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.common.tagview;
2 |
3 | import android.graphics.Color;
4 |
5 | /**
6 | * Created by maxiee on 15-6-16.
7 | *
8 | * Modify from kaedea/Android-Cloud-TagView-Plus (https://github.com/kaedea/Android-Cloud-TagView-Plus)
9 | *
10 | */
11 | public class Constants {
12 |
13 | //use dp and sp, not px
14 |
15 | //----------------- separator TagView-----------------//
16 | public static final float DEFAULT_LINE_MARGIN = 5;
17 | public static final float DEFAULT_TAG_MARGIN = 5;
18 | public static final float DEFAULT_TAG_TEXT_PADDING_LEFT = 8;
19 | public static final float DEFAULT_TAG_TEXT_PADDING_TOP = 5;
20 | public static final float DEFAULT_TAG_TEXT_PADDING_RIGHT = 8;
21 | public static final float DEFAULT_TAG_TEXT_PADDING_BOTTOM = 5;
22 |
23 | public static final float LAYOUT_WIDTH_OFFSET = 2;
24 |
25 | //----------------- separator Tag Item-----------------//
26 | public static final float DEFAULT_TAG_TEXT_SIZE = 14f;
27 | public static final float DEFAULT_TAG_DELETE_INDICATOR_SIZE = 14f;
28 | public static final float DEFAULT_TAG_LAYOUT_BORDER_SIZE = 0f;
29 | public static final float DEFAULT_TAG_RADIUS = 10;
30 | public static final int DEFAULT_TAG_LAYOUT_COLOR = Color.parseColor("#EF9A9A");
31 | public static final int DEFAULT_TAG_LAYOUT_COLOR_PRESS = Color.parseColor("#88363636");
32 | public static final int DEFAULT_TAG_TEXT_COLOR = Color.parseColor("#ffffff");
33 | public static final int DEFAULT_TAG_DELETE_INDICATOR_COLOR = Color.parseColor("#ffffff");
34 | public static final int DEFAULT_TAG_LAYOUT_BORDER_COLOR = Color.parseColor("#ffffff");
35 | public static final String DEFAULT_TAG_DELETE_ICON = "×";
36 | public static final boolean DEFAULT_TAG_IS_DELETABLE = false;
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/data/BaseEventManager.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.data;
2 |
3 | import android.content.Context;
4 |
5 | import com.maxiee.heartbeat.model.Event;
6 |
7 | import java.util.ArrayList;
8 |
9 | /**
10 | * Created by maxiee on 15/11/10.
11 | */
12 | abstract class BaseEventManager {
13 |
14 | protected Context mContext;
15 | protected ArrayList mEventList;
16 |
17 | public BaseEventManager(Context context) {
18 | mContext = context;
19 | }
20 |
21 | abstract void reload();
22 |
23 | public ArrayList getEvents() {
24 | return mEventList;
25 | }
26 |
27 | public void addEvent(Event event) {
28 | for (int i=0; i e.getTimestamp()) {
31 | mEventList.add(i, event);
32 | return;
33 | }
34 | }
35 | mEventList.add(event);
36 | }
37 |
38 | public void deleteEvent(long key) {
39 | int indexEvent = findFromList(key, mEventList);
40 | if (indexEvent >= 0) mEventList.remove(indexEvent);
41 | }
42 |
43 | public void updateEvent(Event e) {
44 | int indexEvent = findFromList(e.getId(), mEventList);
45 | mEventList.remove(indexEvent);
46 | addEvent(e);
47 | }
48 |
49 | public boolean isEmpty() {
50 | return mEventList.isEmpty();
51 | }
52 |
53 | public int size() {
54 | return mEventList.size();
55 | }
56 |
57 | private static int findFromList(long key, ArrayList list) {
58 | for (int i=0; i mData = new ArrayList<>();
20 |
21 | public EventManager(Context context) {
22 | super(context);
23 | reload();
24 | }
25 |
26 | @Override
27 | public void reload() {
28 | if (mEventList != null) mEventList.clear();
29 | mEventList = EventUtils.getAllEvents(mContext);
30 | reloadDayCardData();
31 | }
32 |
33 | public void reloadDayCardData() {
34 | StopWatch stopWatch = new StopWatch(TAG, "reloadDayCardData use time");
35 | mData.clear();
36 | parseData(mEventList);
37 | stopWatch.stop();
38 | }
39 |
40 | private void parseData(ArrayList eventList) {
41 | long dayStart = Long.MIN_VALUE;
42 | DayCard dayCard = null;
43 | for (Event e : eventList) {
44 | if (dayCard == null) {
45 | dayStart = TimeUtils.getDayStart(e.getTimestamp());
46 | dayCard = new DayCard(dayStart, e);
47 | continue;
48 | }
49 | if (TimeUtils.isInSameDay(dayStart, e.getTimestamp())) {
50 | dayCard.addEvent(e);
51 | } else {
52 | mData.add(dayCard);
53 | dayStart = TimeUtils.getDayStart(e.getTimestamp());
54 | dayCard = new DayCard(dayStart, e);
55 | }
56 | }
57 | if (dayCard != null) mData.add(dayCard);
58 | }
59 |
60 | public ArrayList getDayCardData() {return mData;}
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/data/TodayManager.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.data;
2 |
3 | import android.content.Context;
4 |
5 | import com.maxiee.heartbeat.database.utils.EventUtils;
6 | import com.maxiee.heartbeat.database.utils.ThoughtUtils;
7 | import com.maxiee.heartbeat.model.Event;
8 |
9 | import java.util.ArrayList;
10 |
11 | /**
12 | * Created by maxiee on 15/11/10.
13 | */
14 | public class TodayManager extends BaseEventManager{
15 |
16 | public TodayManager(Context context) {
17 | super(context);
18 | mEventList = new ArrayList<>();
19 | reload();
20 | }
21 |
22 | @Override
23 | void reload() {
24 | if (mEventList != null) mEventList.clear();
25 | mEventList.addAll(EventUtils.getToday(mContext));
26 | }
27 |
28 | @Override
29 | public void addEvent(Event event) {
30 | reload();
31 | }
32 |
33 | @Override
34 | public void updateEvent(Event e) {
35 | reload();
36 | }
37 |
38 | public int countTodayThought() {
39 | return ThoughtUtils.getTodayCount(mContext);
40 | }
41 |
42 | public int countTodayEvent() {
43 | return mEventList.size();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/database/DatabaseHelper.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.database;
2 |
3 | import android.content.Context;
4 | import android.database.sqlite.SQLiteDatabase;
5 | import android.database.sqlite.SQLiteOpenHelper;
6 |
7 | import com.maxiee.heartbeat.database.api.ImageUriUpgradeApi;
8 | import com.maxiee.heartbeat.database.tables.CrashTable;
9 | import com.maxiee.heartbeat.database.tables.EventImageRelationTable;
10 | import com.maxiee.heartbeat.database.tables.EventLabelRelationTable;
11 | import com.maxiee.heartbeat.database.tables.EventThoughtRelationTable;
12 | import com.maxiee.heartbeat.database.tables.EventsTable;
13 | import com.maxiee.heartbeat.database.tables.ImageTable;
14 | import com.maxiee.heartbeat.database.tables.LabelsTable;
15 | import com.maxiee.heartbeat.database.tables.ThoughtResTable;
16 | import com.maxiee.heartbeat.database.tables.ThoughtsTable;
17 |
18 | /**
19 | * Created by maxiee on 15-6-11.
20 | */
21 | public class DatabaseHelper extends SQLiteOpenHelper {
22 |
23 | private final static String DB_NAME = "heartbeat";
24 | private final static int DB_VER = 4;
25 |
26 | private static DatabaseHelper instance;
27 | private Context mContext;
28 |
29 | private DatabaseHelper(Context context) {
30 | super(context, DB_NAME, null, DB_VER);
31 | mContext = context;
32 | }
33 |
34 | @Override
35 | public void onCreate(SQLiteDatabase db) {
36 | db.execSQL(EventsTable.CREATE);
37 | db.execSQL(LabelsTable.CREATE);
38 | db.execSQL(EventLabelRelationTable.CREATE);
39 | db.execSQL(ThoughtsTable.CREATE);
40 | db.execSQL(EventThoughtRelationTable.CREATE);
41 | db.execSQL(ImageTable.CREATE);
42 | db.execSQL(EventImageRelationTable.CREATE);
43 | db.execSQL(CrashTable.CREATE);
44 | db.execSQL(ThoughtResTable.CREATE);
45 | }
46 |
47 | @Override
48 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
49 | if (oldVersion == 1) {
50 | db.execSQL(ImageTable.CREATE);
51 | db.execSQL(EventImageRelationTable.CREATE);
52 | }
53 | if (oldVersion <= 2) {
54 | db.execSQL(CrashTable.CREATE);
55 | }
56 | if (oldVersion <= 3) {
57 | db.execSQL(ThoughtResTable.CREATE);
58 | // upgrade items in ImageTable
59 | ImageUriUpgradeApi.exec(mContext, db);
60 | }
61 | }
62 |
63 | public static synchronized DatabaseHelper instance(Context context) {
64 | if (instance == null) {
65 | instance = new DatabaseHelper(context);
66 | }
67 | return instance;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/database/api/AddCrashApi.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.database.api;
2 |
3 | import android.content.ContentValues;
4 | import android.content.Context;
5 |
6 | import com.maxiee.heartbeat.database.tables.CrashTable;
7 |
8 | /**
9 | * Created by maxiee on 15-7-11.
10 | */
11 | public class AddCrashApi extends BaseDBApi{
12 |
13 | private String mLog;
14 |
15 | public AddCrashApi(Context context,
16 | String log) {
17 | super(context);
18 | mLog = log;
19 | }
20 |
21 | public void exec() {
22 | ContentValues values = new ContentValues();
23 | values.put(CrashTable.LOG, mLog);
24 | values.put(CrashTable.TIMESTAMP, System.currentTimeMillis());
25 | add(CrashTable.NAME, values);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/database/api/BaseDBApi.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.database.api;
2 |
3 | import android.content.ContentValues;
4 | import android.content.Context;
5 | import android.database.sqlite.SQLiteDatabase;
6 |
7 | import com.maxiee.heartbeat.database.DatabaseHelper;
8 |
9 | /**
10 | * Created by maxiee on 15-6-11.
11 | */
12 | public abstract class BaseDBApi {
13 |
14 | public static final String THOUGHT = "thought";
15 | public static final String TIMESTAMP = "timestamp";
16 |
17 | protected DatabaseHelper mDatabaseHelper;
18 | protected Context mContext;
19 |
20 | public BaseDBApi(Context context) {
21 | mDatabaseHelper = DatabaseHelper.instance(context);
22 | mContext = context;
23 | }
24 |
25 | protected long add(String table, ContentValues values) {
26 | SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
27 | db.beginTransaction();
28 | long key = db.insert(table, null, values);
29 | db.setTransactionSuccessful();
30 | db.endTransaction();
31 |
32 | return key;
33 | };
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/database/api/GetAllCrashesApi.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.database.api;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 |
6 | import com.maxiee.heartbeat.database.tables.CrashTable;
7 | import com.maxiee.heartbeat.model.Crash;
8 |
9 | import java.util.ArrayList;
10 |
11 | /**
12 | * Created by maxiee on 15-7-11.
13 | */
14 | public class GetAllCrashesApi extends BaseDBApi {
15 | public GetAllCrashesApi(Context context) {
16 | super(context);
17 | }
18 |
19 | public ArrayList exec() {
20 | Cursor cursor = mDatabaseHelper.getReadableDatabase().query(
21 | CrashTable.NAME,
22 | new String[] {
23 | CrashTable.LOG,
24 | CrashTable.TIMESTAMP
25 | },
26 | null,
27 | null, null, null, null
28 | );
29 |
30 | ArrayList crashes = new ArrayList<>();
31 |
32 | if (cursor.getCount() < 1)
33 | return crashes;
34 |
35 | cursor.moveToFirst();
36 | do {
37 | String log = cursor.getString(
38 | cursor.getColumnIndex(CrashTable.LOG)
39 | );
40 | long timestamp = cursor.getLong(
41 | cursor.getColumnIndex(CrashTable.TIMESTAMP)
42 | );
43 | crashes.add(0, new Crash(log, timestamp));
44 | } while (cursor.moveToNext());
45 |
46 | cursor.close();
47 | return crashes;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/database/api/GetCountByNameApi.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.database.api;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 | import android.database.DatabaseUtils;
6 |
7 | import com.maxiee.heartbeat.database.tables.EventsTable;
8 | import com.maxiee.heartbeat.database.tables.ThoughtsTable;
9 |
10 | /**
11 | * Created by maxiee on 15-7-16.
12 | */
13 | public class GetCountByNameApi extends BaseDBApi{
14 | public final static String EVENT = EventsTable.NAME;
15 | public final static String THOUGHT = ThoughtsTable.NAME;
16 |
17 | public GetCountByNameApi(Context context) {
18 | super(context);
19 | }
20 |
21 | public long exec(String table) {
22 | return DatabaseUtils.queryNumEntries(mDatabaseHelper.getReadableDatabase(), table);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/database/api/GetCountSpecDayApi.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.database.api;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 |
6 | import com.maxiee.heartbeat.database.tables.EventsTable;
7 | import com.maxiee.heartbeat.database.tables.ThoughtsTable;
8 |
9 | import java.util.Calendar;
10 |
11 | /**
12 | * Created by maxiee on 15-7-16.
13 | */
14 | public class GetCountSpecDayApi extends BaseDBApi {
15 | public final static String EVENT = EventsTable.NAME;
16 | public final static String THOUGHT = ThoughtsTable.NAME;
17 |
18 | public GetCountSpecDayApi(Context context) {
19 | super(context);
20 | }
21 |
22 | public int exec(Calendar calendarFrom, String tableName) {
23 | Calendar calendarTo = (Calendar) calendarFrom.clone();
24 | calendarTo.add(Calendar.DAY_OF_MONTH, 1);
25 |
26 | Cursor cursor = mDatabaseHelper.getReadableDatabase().query(
27 | tableName,
28 | new String[] {
29 | EventsTable.ID
30 | },
31 | EventsTable.TIMESTAMP + ">? and " + EventsTable.TIMESTAMP + "",
32 | new String[] {
33 | String.valueOf(calendarFrom.getTimeInMillis()),
34 | String.valueOf(calendarTo.getTimeInMillis())
35 | },
36 | null, null, null
37 | );
38 |
39 | int count = cursor.getCount();
40 | cursor.close();
41 | return count;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/database/api/ImageUriUpgradeApi.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.database.api;
2 |
3 | import android.content.ContentValues;
4 | import android.content.Context;
5 | import android.database.Cursor;
6 | import android.database.sqlite.SQLiteDatabase;
7 | import android.net.Uri;
8 | import android.util.Log;
9 |
10 | import com.maxiee.heartbeat.common.FileUtils;
11 | import com.maxiee.heartbeat.database.tables.ImageTable;
12 | import com.maxiee.heartbeat.database.utils.ImageUtils;
13 |
14 | /**
15 | * Created by maxiee on 15-9-8.
16 | */
17 | public class ImageUriUpgradeApi {
18 | private final static String TAG = ImageUriUpgradeApi.class.getSimpleName();
19 | private final static String URI_CONTENT_PREFIX = "content://";
20 |
21 | public static void exec(Context context, SQLiteDatabase db) {
22 | Cursor cursor = db.query(
23 | ImageTable.NAME,
24 | new String[] {
25 | ImageTable.ID,
26 | ImageTable.URI
27 | },
28 | null,
29 | null, null, null, null
30 | );
31 | if (cursor.getCount() < 1) {
32 | Log.d(TAG, "no items in ImageTable");
33 | return;
34 | }
35 | long[] ids = new long[cursor.getCount()];
36 | String[] uris = new String[cursor.getCount()];
37 | int count = 0;
38 | while (cursor.moveToNext()) {
39 | ids[count] = cursor.getLong(cursor.getColumnIndex(ImageTable.ID));
40 | uris[count] = cursor.getString(cursor.getColumnIndex(ImageTable.URI));
41 | count++;
42 | }
43 | cursor.close();
44 | for (int i=0; i mEventList;
11 |
12 | public DayCard (long timeStamp, Event event) {
13 | mTimeStamp = timeStamp;
14 | mEventList = new ArrayList<>();
15 | mEventList.add(event);
16 | }
17 |
18 | public void addEvent(Event event) {
19 | mEventList.add(event);
20 | }
21 |
22 | public long getTimeStamp() {return mTimeStamp;}
23 |
24 | public ArrayList getEventList() {return mEventList;}
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/model/Event.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.model;
2 |
3 | /**
4 | * Created by maxiee on 15-6-12.
5 | */
6 | public class Event {
7 | private String mEvent;
8 | private long timestamp;
9 | private long mId;
10 |
11 | public Event(
12 | int id,
13 | String mEvent,
14 | long timestamp) {
15 | this.mId = id;
16 | this.mEvent = mEvent;
17 | this.timestamp = timestamp;
18 | }
19 |
20 | public Event(
21 | long id,
22 | String mEvent,
23 | long timestamp) {
24 | this.mId = (int) id;
25 | this.mEvent = mEvent;
26 | this.timestamp = timestamp;
27 | }
28 |
29 | public String getEvent() {
30 | return mEvent;
31 | }
32 |
33 | public long getTimestamp() {
34 | return timestamp;
35 | }
36 |
37 | public long getId() {
38 | return mId;
39 | }
40 |
41 | @Override
42 | public String toString() {
43 | return String.format("[%d][%s]\n", mId, mEvent);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/model/Image.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.model;
2 |
3 | /**
4 | * Created by maxiee on 15/11/10.
5 | */
6 | public class Image {
7 | private long mId;
8 | private String mPath;
9 |
10 | public Image(long id, String path) {
11 | mId = id;
12 | mPath = path;
13 | }
14 |
15 | public long getId() {
16 | return mId;
17 | }
18 |
19 | public String getPath() {
20 | return mPath;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/model/Label.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.model;
2 |
3 | /**
4 | * Created by maxiee on 15-7-10.
5 | */
6 | public class Label {
7 | private long mId;
8 | private String mLabel;
9 |
10 | public Label(long key, String label) {
11 | this.mId = key;
12 | this.mLabel = label;
13 | }
14 |
15 | public long getId() {return mId;}
16 |
17 | public String getLabel() {return mLabel;}
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/model/ThoughtRes.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.model;
2 |
3 | /**
4 | * Created by maxiee on 15/11/11.
5 | */
6 | public class ThoughtRes {
7 | private long id;
8 | private int resType;
9 | private String path;
10 | private long thoughtId;
11 |
12 | public ThoughtRes(long id, int resType, String path, long thoughtId) {
13 | this.id = id;
14 | this.resType = resType;
15 | this.path = path;
16 | this.thoughtId = thoughtId;
17 | }
18 |
19 | public long getId() {
20 | return id;
21 | }
22 |
23 | public void setId(long id) {
24 | this.id = id;
25 | }
26 |
27 | public int getResType() {
28 | return resType;
29 | }
30 |
31 | public void setResType(int resType) {
32 | this.resType = resType;
33 | }
34 |
35 | public String getPath() {
36 | return path;
37 | }
38 |
39 | public void setPath(String path) {
40 | this.path = path;
41 | }
42 |
43 | public long getThoughtId() {
44 | return thoughtId;
45 | }
46 |
47 | public void setThoughtId(long thoughtId) {
48 | this.thoughtId = thoughtId;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/provider/Constant.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.provider;
2 |
3 | /**
4 | * Created by maxiee on 16/1/10.
5 | */
6 | public class Constant {
7 | public static final String BASE_URI = "com.maxiee.heartbeat.provider";
8 | public static final String CATEGORY_EVNET = "event/";
9 | public static final String CATEGORY_THOUGHT = "thought/";
10 | public static final String CATEGORY_THOUGHT_RES = "thought_res/";
11 |
12 | public static final String API_EVENT_RANDOM = CATEGORY_EVNET + "random";
13 | public static final String API_EVENT_ID = CATEGORY_EVNET + "id/#";
14 | public static final String API_THOUGHT_EVENT_ID = CATEGORY_THOUGHT + "event_id/#";
15 | public static final String API_THOUGHT_RES_THOUGHT_ID = CATEGORY_THOUGHT_RES + "thought_id/#";
16 |
17 | public static final int API_EVENT_RANDOM_CODE = 0;
18 | public static final int API_EVENT_ID_CODE = 1;
19 | public static final int API_THOUGHT_EVENT_ID_CODE = 2;
20 | public static final int API_THOUGHT_RES_THOUGHT_ID_CODE = 3;
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/provider/HeartBeatContentProvider.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.provider;
2 |
3 | import android.content.ContentProvider;
4 | import android.content.ContentValues;
5 | import android.content.UriMatcher;
6 | import android.database.Cursor;
7 | import android.net.Uri;
8 |
9 | /**
10 | * Created by maxiee on 16/1/9.
11 | */
12 | public class HeartBeatContentProvider extends ContentProvider {
13 | private UriMatcher mMatcher;
14 | private IProviderEventDelegate mEventDelegate;
15 | private IProviderThoughtDelegate mThoughtDelegate;
16 |
17 | @Override
18 | public boolean onCreate() {
19 | initMatcher();
20 | mEventDelegate = new ProviderEventDelegate();
21 | mThoughtDelegate = new ProviderThoughtDelegete();
22 | return false;
23 | }
24 |
25 | @Override
26 | public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
27 | int code = mMatcher.match(uri);
28 | Cursor cursor = null;
29 | cursor = mEventDelegate.dispatchQuery(code, getContext(), uri);
30 | if (cursor != null) return cursor;
31 | cursor = mThoughtDelegate.dispatchQuery(code, getContext(), uri);
32 | if (cursor != null) return cursor;
33 | return null;
34 | }
35 |
36 | @Override
37 | public String getType(Uri uri) {
38 | return null;
39 | }
40 |
41 | @Override
42 | public Uri insert(Uri uri, ContentValues values) {
43 | return null;
44 | }
45 |
46 | @Override
47 | public int delete(Uri uri, String selection, String[] selectionArgs) {
48 | return 0;
49 | }
50 |
51 | @Override
52 | public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
53 | return 0;
54 | }
55 |
56 | private void initMatcher() {
57 | mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
58 | //TODO wrap into delegates
59 | mMatcher.addURI(Constant.BASE_URI, Constant.API_EVENT_RANDOM, Constant.API_EVENT_RANDOM_CODE);
60 | mMatcher.addURI(Constant.BASE_URI, Constant.API_EVENT_ID, Constant.API_EVENT_ID_CODE);
61 | mMatcher.addURI(Constant.BASE_URI, Constant.API_THOUGHT_EVENT_ID, Constant.API_THOUGHT_EVENT_ID_CODE);
62 | mMatcher.addURI(Constant.BASE_URI, Constant.API_THOUGHT_RES_THOUGHT_ID, Constant.API_THOUGHT_RES_THOUGHT_ID_CODE);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/provider/IProviderEventDelegate.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.provider;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 | import android.net.Uri;
6 |
7 | /**
8 | * Created by maxiee on 16/1/10.
9 | */
10 | public interface IProviderEventDelegate {
11 | Cursor dispatchQuery(int code, Context context, Uri uri);
12 | Cursor random(Context context);
13 | Cursor byId(Context context, long id);
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/provider/IProviderThoughtDelegate.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.provider;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 | import android.net.Uri;
6 |
7 | /**
8 | * Created by maxiee on 16/1/31.
9 | */
10 | public interface IProviderThoughtDelegate {
11 | Cursor dispatchQuery(int code, Context context, Uri uri);
12 | Cursor getThought(Context context, long eventId);
13 | Cursor getThoughtRes(Context context, long thoughtId);
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/provider/ProviderEventDelegate.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.provider;
2 |
3 | import android.content.ContentUris;
4 | import android.content.Context;
5 | import android.database.Cursor;
6 | import android.net.Uri;
7 |
8 | import com.maxiee.heartbeat.database.api.GetCountByNameApi;
9 | import com.maxiee.heartbeat.database.tables.EventsTable;
10 | import com.maxiee.heartbeat.database.utils.DatabaseUtils;
11 |
12 | import java.util.Random;
13 |
14 | /**
15 | * Created by maxiee on 16/1/10.
16 | */
17 | public class ProviderEventDelegate implements IProviderEventDelegate {
18 | @Override
19 | public Cursor dispatchQuery(int code, Context context, Uri uri) {
20 | switch (code) {
21 | case Constant.API_EVENT_RANDOM_CODE: {
22 | return random(context);
23 | }
24 | case Constant.API_EVENT_ID_CODE: {
25 | long id = ContentUris.parseId(uri);
26 | return byId(context, id);
27 | }
28 | default: {
29 | return null;
30 | }
31 | }
32 | }
33 |
34 | @Override
35 | public Cursor random(Context context) {
36 | long eventCount = new GetCountByNameApi(context).exec(GetCountByNameApi.EVENT);
37 | int randIndex = (int) (new Random().nextDouble() * eventCount);
38 | Cursor cursor = DatabaseUtils.getReadableDatabase(context).rawQuery(
39 | "SELECT " + EventsTable.ID + ", " + EventsTable.EVENT + ", " + EventsTable.TIMESTAMP
40 | + " FROM " + EventsTable.NAME + " LIMIT 1 OFFSET " + String.valueOf(randIndex), null);
41 | return cursor;
42 | }
43 |
44 | @Override
45 | public Cursor byId(Context context, long id) {
46 | Cursor cursor = DatabaseUtils.getReadableDatabase(context).rawQuery(
47 | "SELECT " + EventsTable.ID + ", " + EventsTable.EVENT + ", " + EventsTable.TIMESTAMP
48 | + " FROM " + EventsTable.NAME + " LIMIT 1 OFFSET " + String.valueOf(id), null);
49 | return cursor;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/provider/ProviderThoughtDelegete.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.provider;
2 |
3 | import android.content.ContentUris;
4 | import android.content.Context;
5 | import android.database.Cursor;
6 | import android.net.Uri;
7 |
8 | import com.maxiee.heartbeat.database.tables.EventThoughtRelationTable;
9 | import com.maxiee.heartbeat.database.tables.ThoughtResTable;
10 | import com.maxiee.heartbeat.database.tables.ThoughtsTable;
11 | import com.maxiee.heartbeat.database.utils.DatabaseUtils;
12 |
13 | /**
14 | * Created by maxiee on 16/1/31.
15 | */
16 | public class ProviderThoughtDelegete implements IProviderThoughtDelegate{
17 | @Override
18 | public Cursor dispatchQuery(int code, Context context, Uri uri) {
19 | switch (code) {
20 | case Constant.API_THOUGHT_EVENT_ID_CODE: {
21 | long id = ContentUris.parseId(uri);
22 | return getThought(context, id);
23 | }
24 | case Constant.API_THOUGHT_RES_THOUGHT_ID_CODE: {
25 | long id = ContentUris.parseId(uri);
26 | return getThoughtRes(context, id);
27 | }
28 | default: {
29 | return null;
30 | }
31 | }
32 | }
33 |
34 | @Override
35 | public Cursor getThought(Context context, long eventId) {
36 | final String rawSQL =
37 | "SELECT " + ThoughtsTable.NAME + "." + ThoughtsTable.ID + ", " + ThoughtsTable.THOUGHT + ", " + ThoughtsTable.TIMESTAMP + ", "
38 | + EventThoughtRelationTable.EVENT_ID + " FROM " + ThoughtsTable.NAME + " JOIN " + EventThoughtRelationTable.NAME
39 | + " ON " + ThoughtsTable.NAME + "." + ThoughtsTable.ID + "=" + EventThoughtRelationTable.NAME + "." + EventThoughtRelationTable.THOUGHT_ID
40 | + " WHERE " + EventThoughtRelationTable.EVENT_ID + "=?"
41 | + " ORDER BY " + ThoughtsTable.TIMESTAMP + " ASC;";
42 | return DatabaseUtils.getReadableDatabase(context).rawQuery(
43 | rawSQL,
44 | new String[] { String.valueOf(eventId)});
45 | }
46 |
47 | @Override
48 | public Cursor getThoughtRes(Context context, long thoughtId) {
49 | return DatabaseUtils.query(
50 | context, ThoughtResTable.NAME,
51 | new String[] {ThoughtResTable.ID, ThoughtResTable.THOUGHT_ID, ThoughtResTable.TYPE, ThoughtResTable.PATH},
52 | ThoughtResTable.THOUGHT_ID + "=?",
53 | new String[] {String.valueOf(thoughtId)});
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/support/CrashHandler.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.support;
2 |
3 | import android.content.Context;
4 | import android.content.pm.PackageInfo;
5 | import android.os.Build;
6 | import android.util.Log;
7 |
8 | import com.maxiee.heartbeat.database.api.AddCrashApi;
9 |
10 | /**
11 | * Created by maxiee on 15-7-11.
12 | *
13 | * Learning from BlackLight (https://github.com/PaperAirplane-Dev-Team/BlackLight)
14 | */
15 | public class CrashHandler implements Thread.UncaughtExceptionHandler{
16 |
17 | private static String ANDROID = Build.VERSION.RELEASE;
18 | private static String MODEL = Build.MODEL;
19 | private static String MANUFACTURER = Build.MANUFACTURER;
20 |
21 | public static String VERSION = "Unknown";
22 |
23 | private Thread.UncaughtExceptionHandler mPrevious;
24 | private Context mContext;
25 |
26 | public void init(Context context) {
27 | mContext = context;
28 | try {
29 | PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
30 | VERSION = info.versionName + " (" + info.versionCode + ")";
31 | } catch (Exception e) {
32 | throw new RuntimeException(e);
33 | }
34 | }
35 |
36 | public static void register(Context context) {
37 | new CrashHandler().init(context);
38 | }
39 |
40 | private CrashHandler() {
41 | mPrevious = Thread.currentThread().getUncaughtExceptionHandler();
42 | Thread.currentThread().setUncaughtExceptionHandler(this);
43 | }
44 |
45 | @Override
46 | public void uncaughtException(Thread thread, Throwable throwable) {
47 | String log = "";
48 |
49 | log += "Android Version: " + ANDROID + "\n";
50 | log += "Device Model: " + MODEL + "\n";
51 | log += "Device Manufacturer: " + MANUFACTURER + "\n";
52 | log += "App Version: " + VERSION + "\n";
53 | log += "*********************\n";
54 | log += throwable.toString() + "\n";
55 | log += Log.getStackTraceString(throwable);
56 |
57 | new AddCrashApi(mContext, log).exec();
58 |
59 | if (mPrevious != null) {
60 | mPrevious.uncaughtException(thread, throwable);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/support/StopWatch.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.support;
2 |
3 | import android.util.Log;
4 |
5 | /**
6 | * Created by maxiee on 15/12/9.
7 | */
8 | public class StopWatch {
9 | private String mWords, mTag;
10 | private long mCurrent;
11 |
12 | public StopWatch(String tag, String words) {
13 | mTag = tag;
14 | mWords = words;
15 | mCurrent = System.currentTimeMillis();
16 | }
17 |
18 | public void stop() {
19 | long now = System.currentTimeMillis();
20 | Log.d(mTag, String.format("[%.4fs]%s\n", (now - mCurrent) / 1000f, mWords));
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/ui/CrashDetailActivity.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.ui;
2 |
3 | import android.content.ClipData;
4 | import android.content.ClipboardManager;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.support.v7.widget.Toolbar;
8 | import android.view.Menu;
9 | import android.view.MenuItem;
10 | import android.widget.TextView;
11 | import android.widget.Toast;
12 |
13 | import com.maxiee.heartbeat.R;
14 | import com.maxiee.heartbeat.model.Crash;
15 | import com.maxiee.heartbeat.ui.common.BaseActivity;
16 |
17 | /**
18 | * Created by maxiee on 15-7-11.
19 | */
20 | public class CrashDetailActivity extends BaseActivity {
21 |
22 | private Toolbar mToolbar;
23 | private TextView mTvCrash;
24 | private String mCrash;
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_crash_detail);
30 |
31 | mToolbar = (Toolbar) findViewById(R.id.toolbar);
32 | setSupportActionBar(mToolbar);
33 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
34 |
35 | mTvCrash = (TextView) findViewById(R.id.tv_crash);
36 |
37 | Intent intent = getIntent();
38 | mCrash = intent.getStringExtra(Crash.LOG);
39 | mTvCrash.setText(mCrash);
40 |
41 | setTitle(getString(R.string.settings_crash));
42 | }
43 |
44 | @Override
45 | public boolean onCreateOptionsMenu(Menu menu) {
46 | getMenuInflater().inflate(R.menu.menu_crash_detail, menu);
47 | return true;
48 | }
49 |
50 | @Override
51 | public boolean onOptionsItemSelected(MenuItem item) {
52 | int id = item.getItemId();
53 | if(id == R.id.clip_board) {
54 | ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
55 | ClipData clip = ClipData.newPlainText("crash report", mCrash);
56 | clipboard.setPrimaryClip(clip);
57 | Toast.makeText(CrashDetailActivity.this, getString(R.string.copy_finished), Toast.LENGTH_LONG).show();
58 | }
59 | if(id == R.id.share) {
60 | Intent sendIntent = new Intent();
61 | sendIntent.setAction(Intent.ACTION_SEND);
62 | sendIntent.putExtra(Intent.EXTRA_TEXT, mCrash);
63 | sendIntent.setType("text/plain");
64 | startActivity(sendIntent);
65 | }
66 | return super.onOptionsItemSelected(item);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/ui/CrashListActivity.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.ui;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.widget.LinearLayoutManager;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.support.v7.widget.Toolbar;
7 | import android.view.MenuItem;
8 |
9 | import com.maxiee.heartbeat.R;
10 | import com.maxiee.heartbeat.database.api.GetAllCrashesApi;
11 | import com.maxiee.heartbeat.model.Crash;
12 | import com.maxiee.heartbeat.ui.adapter.CrashListAdapter;
13 | import com.maxiee.heartbeat.ui.common.BaseActivity;
14 |
15 | import java.util.ArrayList;
16 |
17 | /**
18 | * Created by maxiee on 15-7-11.
19 | */
20 | public class CrashListActivity extends BaseActivity {
21 |
22 | private Toolbar mToolbar;
23 | private RecyclerView mRecyclerView;
24 |
25 | @Override
26 | protected void onCreate(Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | setContentView(R.layout.activity_crash_list);
29 |
30 | mToolbar = (Toolbar) findViewById(R.id.toolbar);
31 | setSupportActionBar(mToolbar);
32 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
33 |
34 | mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
35 | mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
36 |
37 | ArrayList crashes = new GetAllCrashesApi(this).exec();
38 | mRecyclerView.setAdapter(new CrashListAdapter(crashes));
39 |
40 | setTitle(getString(R.string.settings_crash));
41 | }
42 |
43 | @Override
44 | public boolean onOptionsItemSelected(MenuItem item) {
45 | int id = item.getItemId();
46 | if (id == android.R.id.home) {
47 | this.onBackPressed();
48 | return true;
49 | }
50 | return super.onOptionsItemSelected(item);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/ui/GalleryActivity.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.ui;
2 |
3 | import android.graphics.Color;
4 | import android.os.Bundle;
5 | import android.support.v7.widget.Toolbar;
6 | import android.view.MenuItem;
7 | import android.view.View;
8 |
9 | import com.bumptech.glide.Glide;
10 | import com.maxiee.heartbeat.R;
11 | import com.maxiee.heartbeat.common.GalleryUtils;
12 | import com.maxiee.heartbeat.database.utils.ImageUtils;
13 | import com.maxiee.heartbeat.ui.common.BaseActivity;
14 |
15 | import uk.co.senab.photoview.PhotoView;
16 | import uk.co.senab.photoview.PhotoViewAttacher;
17 |
18 | /**
19 | * Created by maxiee on 15-8-26.
20 | */
21 | public class GalleryActivity extends BaseActivity {
22 | public static final String EVENT_ID = "event_id";
23 | public static final String PATH = "path";
24 | private PhotoView mImage;
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_gallery);
30 |
31 | long eventId = getIntent().getLongExtra(EVENT_ID, -1);
32 | String path = "";
33 | if (eventId == -1) {
34 | path = getIntent().getStringExtra(PATH);
35 | }
36 |
37 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
38 | toolbar.setBackgroundColor(Color.BLACK);
39 | toolbar.setTitle("");
40 | toolbar.setAlpha(0.6f);
41 | setSupportActionBar(toolbar);
42 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
43 |
44 | mImage = (PhotoView) findViewById(R.id.imageview);
45 |
46 | mImage.setOnPhotoTapListener(new PhotoViewAttacher.OnPhotoTapListener() {
47 | @Override
48 | public void onPhotoTap(View view, float x, float y) {
49 | finish();
50 | }
51 | });
52 |
53 | if (eventId != -1) {
54 | String imagePath = ImageUtils.getImageByEventId(this, eventId).getPath();
55 | Glide.with(this).load(GalleryUtils.getImagePath(imagePath)).into(mImage);
56 | } else {
57 | Glide.with(this).load(GalleryUtils.getImagePath(path)).into(mImage);
58 | }
59 | }
60 |
61 | @Override
62 | public boolean onOptionsItemSelected(MenuItem item) {
63 | int id = item.getItemId();
64 | if (id == android.R.id.home) {
65 | this.onBackPressed();
66 | return true;
67 | }
68 | return super.onOptionsItemSelected(item);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/ui/HelpCenterActivity.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.ui;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.widget.LinearLayoutManager;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.support.v7.widget.Toolbar;
7 | import android.view.MenuItem;
8 |
9 | import com.maxiee.heartbeat.R;
10 | import com.maxiee.heartbeat.ui.adapter.HelpListAdapter;
11 | import com.maxiee.heartbeat.ui.common.BaseActivity;
12 | import com.maxiee.heartbeat.ui.common.RecyclerInsetsDecoration;
13 |
14 | import butterknife.Bind;
15 | import butterknife.ButterKnife;
16 |
17 | /**
18 | * Created by maxiee on 15/12/15.
19 | */
20 | public class HelpCenterActivity extends BaseActivity {
21 |
22 | public static final String[] TITLES = new String[] {
23 | /*1: */ "心动是一款怎样的记录软件",
24 | /*2: */ "三级信息结构:标签-事件-感想",
25 | /*999: */ "捐赠感谢名单"
26 | };
27 |
28 | public static final String[] DESCRIPTIONS = new String[] {
29 | /*1: */ "心动是一款怎样的记录软件?背后的理念如何?本文将一一进行阐述……",
30 | /*2: */ "正如前文中说的,心动改进了传统日记的信息组织方式,也就是心……",
31 | /*999: */ "为了表达我的感谢,我建立了这个捐赠感谢名单,每一位捐赠用户……"
32 | };
33 |
34 | public static final String[] FILENAMES = new String[] {
35 | /*1: */ "what_heartbeat_is.html",
36 | /*2: */ "label_event_thought.html",
37 | /*999: */ "donate_list.html"
38 | };
39 |
40 | @Bind(R.id.toolbar) Toolbar mToolbar;
41 | @Bind(R.id.recyclerview) RecyclerView mRecyclerView;
42 |
43 | @Override
44 | protected void onCreate(Bundle savedInstanceState) {
45 | super.onCreate(savedInstanceState);
46 | setContentView(R.layout.activity_help_center);
47 | ButterKnife.bind(this);
48 |
49 | setSupportActionBar(mToolbar);
50 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
51 | setTitle(getString(R.string.helpcenter));
52 |
53 | HelpListAdapter adapter = new HelpListAdapter(TITLES, DESCRIPTIONS, FILENAMES);
54 |
55 | mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
56 | mRecyclerView.addItemDecoration(new RecyclerInsetsDecoration(this));
57 | mRecyclerView.setAdapter(adapter);
58 |
59 | }
60 |
61 | @Override
62 | public boolean onOptionsItemSelected(MenuItem item) {
63 | int id = item.getItemId();
64 | if (id == android.R.id.home) {
65 | this.onBackPressed();
66 | return true;
67 | }
68 | return super.onOptionsItemSelected(item);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/ui/HelpCenterDetailActivity.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.ui;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v7.widget.Toolbar;
6 | import android.view.MenuItem;
7 | import android.webkit.WebView;
8 |
9 | import com.maxiee.heartbeat.R;
10 | import com.maxiee.heartbeat.ui.common.BaseActivity;
11 |
12 | import butterknife.Bind;
13 | import butterknife.ButterKnife;
14 |
15 | /**
16 | * Created by maxiee on 15/12/16.
17 | */
18 | public class HelpCenterDetailActivity extends BaseActivity {
19 | public static final String TITLE = "title";
20 | public static final String FILENAME = "filename";
21 | private static final String BASE_URL = "file:///android_asset/";
22 |
23 | @Bind(R.id.toolbar) Toolbar mToolbar;
24 | @Bind(R.id.web) WebView mWebView;
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_help_center_detail);
30 | ButterKnife.bind(this);
31 |
32 | Intent i = getIntent();
33 | String title = i.getStringExtra(TITLE);
34 | String filename = i.getStringExtra(FILENAME);
35 |
36 | setSupportActionBar(mToolbar);
37 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
38 | setTitle(title);
39 |
40 | if (!filename.isEmpty()) {
41 | mWebView.loadUrl(BASE_URL + filename);
42 | }
43 | }
44 |
45 | @Override
46 | public boolean onOptionsItemSelected(MenuItem item) {
47 | int id = item.getItemId();
48 | if (id == android.R.id.home) {
49 | this.onBackPressed();
50 | return true;
51 | }
52 | return super.onOptionsItemSelected(item);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/ui/SearchResultActivity.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.ui;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v7.widget.LinearLayoutManager;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.support.v7.widget.Toolbar;
8 | import android.view.MenuItem;
9 | import android.view.View;
10 | import android.widget.ImageView;
11 | import android.widget.RelativeLayout;
12 |
13 | import com.bumptech.glide.Glide;
14 | import com.maxiee.heartbeat.R;
15 | import com.maxiee.heartbeat.database.utils.EventUtils;
16 | import com.maxiee.heartbeat.model.Event;
17 | import com.maxiee.heartbeat.ui.adapter.EventListAdapter;
18 | import com.maxiee.heartbeat.ui.common.BaseActivity;
19 | import com.maxiee.heartbeat.ui.common.RecyclerInsetsDecoration;
20 |
21 | import java.util.ArrayList;
22 |
23 | /**
24 | * Created by maxiee on 15-7-21.
25 | */
26 | public class SearchResultActivity extends BaseActivity{
27 | private static final String TAG = SearchResultActivity.class.getSimpleName();
28 | private Toolbar mToolbar;
29 | private RecyclerView mRecyclerView;
30 | private RelativeLayout mEmptyLayout;
31 | private ImageView mImageEmpty;
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | setContentView(R.layout.activity_search_result);
37 |
38 | mToolbar = (Toolbar) findViewById(R.id.toolbar);
39 | setSupportActionBar(mToolbar);
40 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
41 |
42 | mEmptyLayout = (RelativeLayout) findViewById(R.id.empty);
43 | mImageEmpty = (ImageView) findViewById(R.id.image_empty);
44 | mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
45 | mRecyclerView.setLayoutManager(new LinearLayoutManager(mRecyclerView.getContext()));
46 | mRecyclerView.addItemDecoration(new RecyclerInsetsDecoration(this));
47 |
48 | Intent i = getIntent();
49 | String search = i.getStringExtra("search");
50 |
51 | if (!search.isEmpty()) {
52 | setTitle(search);
53 | updateEventList(search);
54 | }
55 | }
56 |
57 | @Override
58 | public boolean onOptionsItemSelected(MenuItem item) {
59 | int id = item.getItemId();
60 | if (id == android.R.id.home) {
61 | this.onBackPressed();
62 | return true;
63 | }
64 | return super.onOptionsItemSelected(item);
65 | }
66 |
67 | public void updateEventList(String search) {
68 | ArrayList eventList = EventUtils.searchEvent(this, search);
69 | if (!eventList.isEmpty()) {
70 | mRecyclerView.setAdapter(new EventListAdapter(eventList));
71 | } else {
72 | mRecyclerView.setVisibility(View.GONE);
73 | mEmptyLayout.setVisibility(View.VISIBLE);
74 | Glide.with(this).load(R.drawable.empty_bg1).into(mImageEmpty);
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/ui/SettingsActivity.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.ui;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v7.widget.Toolbar;
6 |
7 | import com.maxiee.heartbeat.R;
8 | import com.maxiee.heartbeat.ui.common.BaseActivity;
9 | import com.maxiee.heartbeat.ui.fragments.SettingsFragment;
10 |
11 | /**
12 | * Created by maxiee on 15-6-28.
13 | */
14 | public class SettingsActivity extends BaseActivity {
15 |
16 | private Toolbar mToolbar;
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | setContentView(R.layout.activity_settings);
22 |
23 | mToolbar = (Toolbar) findViewById(R.id.toolbar);
24 | setSupportActionBar(mToolbar);
25 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
26 |
27 | getFragmentManager()
28 | .beginTransaction()
29 | .replace(R.id.container, new SettingsFragment())
30 | .commit();
31 |
32 | setTitle(getString(R.string.action_settings));
33 | }
34 |
35 | @Override
36 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
37 | super.onActivityResult(requestCode, resultCode, data);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/ui/adapter/CrashListAdapter.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.ui.adapter;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.TextView;
11 |
12 | import com.maxiee.heartbeat.R;
13 | import com.maxiee.heartbeat.common.TimeUtils;
14 | import com.maxiee.heartbeat.model.Crash;
15 | import com.maxiee.heartbeat.ui.CrashDetailActivity;
16 |
17 | import java.util.ArrayList;
18 |
19 | /**
20 | * Created by maxiee on 15-7-11.
21 | */
22 | public class CrashListAdapter extends RecyclerView.Adapter {
23 |
24 | private ArrayList mCrashList;
25 |
26 | public CrashListAdapter(ArrayList crashList) {
27 | this.mCrashList = crashList;
28 | }
29 |
30 | @Override
31 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
32 | View v = LayoutInflater.from(parent.getContext())
33 | .inflate(R.layout.item_crash_card, parent, false);
34 | return new ViewHolder(v);
35 | }
36 |
37 | @Override
38 | public void onBindViewHolder(ViewHolder holder, int position) {
39 | final Crash crash = mCrashList.get(position);
40 |
41 | holder.tvCrash.setText(crash.log);
42 | holder.tvTime.setText(
43 | TimeUtils.parseTime(
44 | holder.mContext,
45 | crash.timeStamp
46 | )
47 | );
48 | holder.mView.setOnClickListener(new View.OnClickListener() {
49 | @Override
50 | public void onClick(View v) {
51 | Context context = v.getContext();
52 | Intent intent = new Intent(context, CrashDetailActivity.class);
53 | intent.putExtra(Crash.LOG, crash.log);
54 | intent.putExtra(Crash.TS, crash.timeStamp);
55 | ((Activity)context).startActivity(intent);
56 | }
57 | });
58 | }
59 |
60 | @Override
61 | public int getItemCount() {
62 | return mCrashList.size();
63 | }
64 |
65 | public class ViewHolder extends RecyclerView.ViewHolder {
66 | public TextView tvCrash, tvTime;
67 | public Context mContext;
68 | public final View mView;
69 |
70 | public ViewHolder(View itemView) {
71 | super(itemView);
72 | mContext = itemView.getContext();
73 | mView = itemView;
74 | tvCrash = (TextView) itemView.findViewById(R.id.tv_crash);
75 | tvTime = (TextView) itemView.findViewById(R.id.tv_time);
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/ui/adapter/HelpListAdapter.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.ui.adapter;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.TextView;
10 |
11 | import com.maxiee.heartbeat.R;
12 | import com.maxiee.heartbeat.ui.HelpCenterDetailActivity;
13 |
14 | import butterknife.Bind;
15 | import butterknife.ButterKnife;
16 |
17 | /**
18 | * Created by maxiee on 15/12/15.
19 | */
20 | public class HelpListAdapter extends RecyclerView.Adapter {
21 |
22 | private String[] mTitles;
23 | private String[] mDescriptions;
24 | private String[] mFilenames;
25 |
26 | public HelpListAdapter(String[] titles, String[] descriptions, String[] filenames) {
27 | mTitles = titles;
28 | mDescriptions = descriptions;
29 | mFilenames = filenames;
30 | }
31 |
32 | @Override
33 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
34 | View v = LayoutInflater.from(parent.getContext())
35 | .inflate(R.layout.item_help_center, parent, false);
36 | return new ViewHolder(v);
37 | }
38 |
39 | @Override
40 | public void onBindViewHolder(ViewHolder holder, int position) {
41 | holder.title.setText(mTitles[position]);
42 | holder.description.setText(mDescriptions[position]);
43 | holder.setOnClickListener(mTitles[position], mFilenames[position]);
44 | }
45 |
46 | @Override
47 | public int getItemCount() {
48 | return mTitles.length;
49 | }
50 |
51 | public class ViewHolder extends RecyclerView.ViewHolder {
52 | @Bind(R.id.title) TextView title;
53 | @Bind(R.id.description) TextView description;
54 | View v;
55 |
56 | public ViewHolder(View itemView) {
57 | super(itemView);
58 | ButterKnife.bind(this, itemView);
59 | v = itemView;
60 | }
61 |
62 | public void setOnClickListener(final String title, final String filename) {
63 | v.setOnClickListener(new View.OnClickListener() {
64 | @Override
65 | public void onClick(View v) {
66 | Context context = v.getContext();
67 | Intent i = new Intent(context, HelpCenterDetailActivity.class);
68 | i.putExtra(HelpCenterDetailActivity.TITLE, title);
69 | i.putExtra(HelpCenterDetailActivity.FILENAME, filename);
70 | context.startActivity(i);
71 | }
72 | });
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/ui/common/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.ui.common;
2 |
3 | import android.os.Build;
4 | import android.os.Bundle;
5 | import android.support.v7.app.AppCompatActivity;
6 |
7 | import com.maxiee.heartbeat.R;
8 | import com.maxiee.heartbeat.common.ThemeUtils;
9 |
10 | /**
11 | * Created by maxiee on 15/10/22.
12 | */
13 | public class BaseActivity extends AppCompatActivity{
14 | private int mCurrentTheme;
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | mCurrentTheme = ThemeUtils.getCurrentActivityTheme(this);
20 | setTheme(mCurrentTheme);
21 | if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
22 | getWindow().setStatusBarColor(ThemeUtils.getAttributeColor(this, R.attr.colorPrimaryDark));
23 | }
24 | }
25 |
26 | @Override
27 | protected void onResume() {
28 | super.onResume();
29 | int newTheme = ThemeUtils.getCurrentActivityTheme(this);
30 | if (mCurrentTheme != newTheme) {
31 | recreate();
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/ui/common/HintSearchBox.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.ui.common;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.View;
6 | import android.widget.EditText;
7 |
8 | import com.quinny898.library.persistentsearch.SearchBox;
9 |
10 | /**
11 | * Created by maxiee on 15/12/12.
12 | */
13 | public class HintSearchBox extends SearchBox {
14 | public HintSearchBox(Context context) {
15 | super(context);
16 | }
17 |
18 | public HintSearchBox(Context context, AttributeSet attrs) {
19 | super(context, attrs);
20 | }
21 |
22 | public HintSearchBox(Context context, AttributeSet attrs, int defStyle) {
23 | super(context, attrs, defStyle);
24 | }
25 |
26 | @Override
27 | public void setLogoText(String text) {
28 | super.setLogoText(text);
29 | View v = this.getRootView();
30 | EditText search = (EditText)this.findViewById(com.quinny898.library.persistentsearch.R.id.search);
31 | search.setHint(text);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/ui/common/RecyclerInsetsDecoration.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.ui.common;
2 |
3 | import android.content.Context;
4 | import android.graphics.Rect;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.view.View;
7 |
8 | import com.maxiee.heartbeat.R;
9 |
10 |
11 | /**
12 | * ItemDecoration implementation that applies an inset margin
13 | * around each child of the RecyclerView. The inset value is controlled
14 | * by a dimension resource.
15 | *
16 | * by Dave Smith at: https://github.com/devunwired/recyclerview-playground
17 | */
18 | public class RecyclerInsetsDecoration extends RecyclerView.ItemDecoration {
19 |
20 | private int mInsets;
21 |
22 | public RecyclerInsetsDecoration(Context context) {
23 | mInsets = context.getResources().getDimensionPixelSize(R.dimen.insets);
24 | }
25 |
26 | @Override
27 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
28 |
29 | //We can supply forced insets for each item view here in the Rect
30 | super.getItemOffsets(outRect, view, parent, state);
31 | outRect.set(mInsets, mInsets, mInsets, mInsets);
32 | }
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/ui/common/mdheaderview/TriView.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.ui.common.mdheaderview;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.graphics.Path;
9 | import android.util.AttributeSet;
10 | import android.view.View;
11 |
12 | import com.maxiee.heartbeat.R;
13 |
14 | /**
15 | * Created by maxiee on 15/11/16.
16 | */
17 | public class TriView extends View{
18 |
19 | public static final int SHADOW_SIZE = 10;
20 |
21 | private Paint mPaint;
22 | private Path mPath;
23 | private int mColor;
24 |
25 | public TriView(Context context) {
26 | super(context);
27 | init(context, null);
28 | }
29 |
30 | public TriView(Context context, AttributeSet attrs) {
31 | super(context, attrs);
32 | init(context, attrs);
33 | }
34 |
35 | public TriView(Context context, AttributeSet attrs, int defStyleAttr) {
36 | super(context, attrs, defStyleAttr);
37 | init(context, attrs);
38 | }
39 |
40 | public void init (Context context, AttributeSet attrs) {
41 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TriView, 0, 0);
42 | mColor = a.getColor(R.styleable.TriView_tri_color, Color.BLACK);
43 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
44 | mPaint.setStyle(Paint.Style.FILL);
45 | mPath = new Path();
46 | a.recycle();
47 | }
48 |
49 | @Override
50 | protected void onDraw(Canvas canvas) {
51 | super.onDraw(canvas);
52 | mPath.moveTo(0, getHeight());
53 | mPath.lineTo(getWidth() / 2, 0);
54 | mPath.lineTo(getWidth(), getHeight());
55 | mPath.lineTo(0, getHeight());
56 | mPaint.setShadowLayer(SHADOW_SIZE, 0, 0, Color.BLACK);
57 | mPaint.setColor(mColor);
58 | canvas.drawPath(mPath, mPaint);
59 | }
60 |
61 | public void setColor(int color) {
62 | mColor = color;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/ui/fragments/EventTodayFragment.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.ui.fragments;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.Fragment;
5 | import android.support.v7.widget.LinearLayoutManager;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.ImageView;
11 | import android.widget.RelativeLayout;
12 |
13 | import com.bumptech.glide.Glide;
14 | import com.maxiee.heartbeat.R;
15 | import com.maxiee.heartbeat.data.DataManager;
16 | import com.maxiee.heartbeat.ui.common.RecyclerInsetsDecoration;
17 |
18 | import butterknife.Bind;
19 | import butterknife.ButterKnife;
20 |
21 | /**
22 | * Created by maxiee on 15-6-23.
23 | */
24 | public class EventTodayFragment extends Fragment{
25 |
26 | @Bind(R.id.recyclerview) RecyclerView mRecyclerView;
27 | @Bind(R.id.empty) RelativeLayout mEmtpyLayout;
28 | @Bind(R.id.image_empty) ImageView mImageEmpty;
29 | private DataManager mDataManager;
30 |
31 | @Override
32 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
33 | View v = inflater.inflate(R.layout.fragment_event_today, container, false);
34 | ButterKnife.bind(this, v);
35 |
36 | mDataManager = DataManager.getInstance(getContext());
37 | mRecyclerView.setLayoutManager(new LinearLayoutManager(mRecyclerView.getContext()));
38 | mRecyclerView.addItemDecoration(new RecyclerInsetsDecoration(getContext()));
39 | mRecyclerView.setAdapter(mDataManager.getTodayAdapter());
40 | updateEventList();
41 |
42 | return v;
43 | }
44 |
45 | public void updateEventList() {
46 | if (!mDataManager.isTodayEmpty()) {
47 | mRecyclerView.setVisibility(View.VISIBLE);
48 | mEmtpyLayout.setVisibility(View.GONE);
49 | mDataManager.notifyDataSetChanged();
50 | } else {
51 | mRecyclerView.setVisibility(View.GONE);
52 | mEmtpyLayout.setVisibility(View.VISIBLE);
53 | Glide.with(getActivity()).load(R.drawable.empty_bg2).into(mImageEmpty);
54 | }
55 | }
56 |
57 | @Override
58 | public void onResume() {
59 | super.onResume();
60 | mDataManager.checkNewDay();
61 | updateEventList();
62 | }
63 |
64 | @Override
65 | public void onDestroyView() {
66 | super.onDestroyView();
67 | ButterKnife.unbind(this);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/com/maxiee/heartbeat/widget/HeartBeatWidgetProvider.java:
--------------------------------------------------------------------------------
1 | package com.maxiee.heartbeat.widget;
2 |
3 | import android.app.PendingIntent;
4 | import android.appwidget.AppWidgetManager;
5 | import android.appwidget.AppWidgetProvider;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.content.res.TypedArray;
9 | import android.widget.RemoteViews;
10 |
11 | import com.maxiee.heartbeat.R;
12 | import com.maxiee.heartbeat.common.ThemeUtils;
13 | import com.maxiee.heartbeat.data.DataManager;
14 | import com.maxiee.heartbeat.ui.AddEventActivity;
15 | import com.maxiee.heartbeat.ui.EntryActivity;
16 |
17 | /**
18 | * Created by maxiee on 16/4/26.
19 | */
20 | public class HeartBeatWidgetProvider extends AppWidgetProvider {
21 |
22 | @Override
23 | public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
24 | final int n = appWidgetIds.length;
25 |
26 | int currentTheme = ThemeUtils.getCurrentActivityTheme(context);
27 | context.setTheme(currentTheme);
28 |
29 | int attrs[] = {R.attr.colorAccent, R.attr.colorPrimary, R.attr.colorPrimaryDark};
30 | TypedArray ta = context.obtainStyledAttributes(currentTheme, attrs);
31 |
32 | int colorAccent = ThemeUtils.getAttributeColor(context, R.attr.colorAccent);
33 | int colorPrimary = ThemeUtils.getAttributeColor(context, R.attr.colorPrimary);
34 | int colorPrimaryDark = ThemeUtils.getAttributeColor(context, R.attr.colorPrimaryDark);
35 |
36 | ta.recycle();
37 |
38 | for (int i=0; i
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 | -
12 |
13 |
14 |
15 |
16 |
17 |
18 | -
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | -
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/circle_timeaxis.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/empty_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/app/src/main/res/drawable/empty_bg.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/empty_bg1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/app/src/main/res/drawable/empty_bg1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/empty_bg2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/app/src/main/res/drawable/empty_bg2.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_crash_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_crash_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_entry.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_gallery.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_help_center.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_help_center_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
22 |
23 |
24 |
25 |
29 |
30 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_label_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
21 |
22 |
32 |
33 |
40 |
41 |
42 |
43 |
44 |
45 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_pattern.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
20 |
21 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_search_result.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
13 |
14 |
15 |
16 |
19 |
20 |
26 |
27 |
32 |
39 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_edit_event.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
15 |
16 |
22 |
23 |
35 |
36 |
42 |
43 |
48 |
49 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_edit_thought.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_new_label.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_new_thought.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
16 |
17 |
25 |
31 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_event_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
18 |
19 |
20 |
25 |
32 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_event_today.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
14 |
19 |
26 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_label_cloud.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
17 |
18 |
22 |
23 |
24 |
25 |
26 |
27 |
32 |
39 |
48 |
49 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/include_activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
22 |
23 |
28 |
29 |
30 |
31 |
36 |
37 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_crash_card.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
21 |
22 |
29 |
30 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_day_card.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
11 |
21 |
26 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_day_card_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
26 |
32 |
36 |
40 |
41 |
42 |
49 |
54 |
62 |
63 |
69 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_event_card.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
20 |
21 |
31 |
32 |
40 |
41 |
51 |
52 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_help_center.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
13 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_thought_timeaxis.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
20 |
21 |
27 |
28 |
34 |
35 |
36 |
37 |
43 |
44 |
50 |
51 |
62 |
63 |
69 |
70 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_today_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
27 |
28 |
35 |
36 |
43 |
44 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/tagview_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
23 |
24 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
15 |
21 |
27 |
34 |
40 |
41 |
42 |
50 |
58 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/dialog_edit_thought.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/dialog_new_thought.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/drawer_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/fragment_eventlist_type.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_crash_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_event_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFF5F5F5
4 | #e7e7e7
5 | #BDBDBD
6 | #96ffffff
7 |
8 | #00000000
9 |
10 | #ffffff
11 | #d4d4d4
12 | #dddddd
13 | #eee
14 |
15 | #00BCD4
16 | #00ACC1
17 | #EF9A9A
18 |
19 | #4CAF50
20 | #388E3C
21 | #FFD600
22 |
23 | #F44336
24 | #D32F2F
25 | #FFAB00
26 |
27 | #303F9F
28 | #1A237E
29 | #AEEA00
30 |
31 | #607D8B
32 | #455A64
33 | #40C4FF
34 |
35 | #9C27B0
36 | #7B1FA2
37 | #FF4081
38 |
39 | #757575
40 | #424242
41 | #FF9100
42 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 35dp
6 | 5dp
7 | 10dp
8 | 2dp
9 | 60dp
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/tagview_attr.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/widget_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/attitude.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.1.0-rc1'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## Project-wide Gradle settings.
2 | #
3 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Tue Sep 29 13:56:58 CST 2015
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jan 15 23:52:52 CST 2016
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/icon.png
--------------------------------------------------------------------------------
/multi-image-selector/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/multi-image-selector/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | minSdkVersion 15
9 | targetSdkVersion 23
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(dir: 'libs', include: ['*.jar'])
23 | compile 'com.android.support:appcompat-v7:23.1.1'
24 | compile 'com.squareup.picasso:picasso:2.4.0'
25 | }
26 |
--------------------------------------------------------------------------------
/multi-image-selector/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in F:/Nereo/Program/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/multi-image-selector/src/androidTest/java/me/nereo/multi_image_selector/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package me.nereo.multi_image_selector;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/multi-image-selector/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/java/me/nereo/multi_image_selector/bean/Folder.java:
--------------------------------------------------------------------------------
1 | package me.nereo.multi_image_selector.bean;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * 文件夹
9 | * Created by Nereo on 2015/4/7.
10 | */
11 | public class Folder {
12 | public String name;
13 | public String path;
14 | public Image cover;
15 | public List images;
16 |
17 | @Override
18 | public boolean equals(Object o) {
19 | try {
20 | Folder other = (Folder) o;
21 | return TextUtils.equals(other.path, path);
22 | }catch (ClassCastException e){
23 | e.printStackTrace();
24 | }
25 | return super.equals(o);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/java/me/nereo/multi_image_selector/bean/Image.java:
--------------------------------------------------------------------------------
1 | package me.nereo.multi_image_selector.bean;
2 |
3 | /**
4 | * 图片实体
5 | * Created by Nereo on 2015/4/7.
6 | */
7 | public class Image {
8 | public String path;
9 | public String name;
10 | public long time;
11 |
12 | public Image(String path, String name, long time){
13 | this.path = path;
14 | this.name = name;
15 | this.time = time;
16 | }
17 |
18 | @Override
19 | public boolean equals(Object o) {
20 | try {
21 | Image other = (Image) o;
22 | return this.path.equalsIgnoreCase(other.path);
23 | }catch (ClassCastException e){
24 | e.printStackTrace();
25 | }
26 | return super.equals(o);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/java/me/nereo/multi_image_selector/utils/ScreenUtils.java:
--------------------------------------------------------------------------------
1 | package me.nereo.multi_image_selector.utils;
2 |
3 | import android.content.Context;
4 | import android.graphics.Point;
5 | import android.os.Build;
6 | import android.view.Display;
7 | import android.view.WindowManager;
8 |
9 | /**
10 | * 屏幕工具
11 | * Created by nereo on 15/11/19.
12 | * Updated by nereo on 2016/1/19.
13 | */
14 | public class ScreenUtils {
15 |
16 | public static Point getScreenSize(Context context){
17 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
18 | Display display = wm.getDefaultDisplay();
19 | Point out = new Point();
20 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
21 | display.getSize(out);
22 | }else{
23 | int width = display.getWidth();
24 | int height = display.getHeight();
25 | out.set(width, height);
26 | }
27 | return out;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/java/me/nereo/multi_image_selector/utils/TimeUtils.java:
--------------------------------------------------------------------------------
1 | package me.nereo.multi_image_selector.utils;
2 |
3 | import java.io.File;
4 | import java.text.SimpleDateFormat;
5 | import java.util.Date;
6 | import java.util.Locale;
7 |
8 | /**
9 | * 时间处理工具
10 | * Created by Nereo on 2015/4/8.
11 | */
12 | public class TimeUtils {
13 |
14 | public static String timeFormat(long timeMillis, String pattern){
15 | SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.CHINA);
16 | return format.format(new Date(timeMillis));
17 | }
18 |
19 | public static String formatPhotoDate(long time){
20 | return timeFormat(time, "yyyy-MM-dd");
21 | }
22 |
23 | public static String formatPhotoDate(String path){
24 | File file = new File(path);
25 | if(file.exists()){
26 | long time = file.lastModified();
27 | return formatPhotoDate(time);
28 | }
29 | return "1970-01-01";
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/java/me/nereo/multi_image_selector/view/SquareFrameLayout.java:
--------------------------------------------------------------------------------
1 | package me.nereo.multi_image_selector.view;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.FrameLayout;
6 |
7 | /**
8 | * Created by nereo on 15/11/10.
9 | */
10 | public class SquareFrameLayout extends FrameLayout{
11 | public SquareFrameLayout(Context context) {
12 | super(context);
13 | }
14 |
15 | public SquareFrameLayout(Context context, AttributeSet attrs) {
16 | super(context, attrs);
17 | }
18 |
19 | @Override
20 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
21 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
22 | setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth());
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/java/me/nereo/multi_image_selector/view/SquaredImageView.java:
--------------------------------------------------------------------------------
1 | package me.nereo.multi_image_selector.view;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.ImageView;
6 |
7 | /** An image view which always remains square with respect to its width. */
8 | class SquaredImageView extends ImageView {
9 | public SquaredImageView(Context context) {
10 | super(context);
11 | }
12 |
13 | public SquaredImageView(Context context, AttributeSet attrs) {
14 | super(context, attrs);
15 | }
16 |
17 | @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
18 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
19 | setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth());
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/color/default_text_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/color/folder_text_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/drawable-xhdpi/btn_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/multi-image-selector/src/main/res/drawable-xhdpi/btn_back.png
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/drawable-xhdpi/default_check_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/multi-image-selector/src/main/res/drawable-xhdpi/default_check_s.png
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/drawable-xhdpi/ic_menu_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/multi-image-selector/src/main/res/drawable-xhdpi/ic_menu_back.png
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/drawable-xhdpi/selector_indicator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/multi-image-selector/src/main/res/drawable-xhdpi/selector_indicator.png
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/drawable-xxhdpi/asv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/multi-image-selector/src/main/res/drawable-xxhdpi/asv.png
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/drawable-xxhdpi/asy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/multi-image-selector/src/main/res/drawable-xxhdpi/asy.png
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/drawable-xxhdpi/btn_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/multi-image-selector/src/main/res/drawable-xxhdpi/btn_selected.png
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/drawable-xxhdpi/btn_unselected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/multi-image-selector/src/main/res/drawable-xxhdpi/btn_unselected.png
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/drawable-xxhdpi/default_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/multi-image-selector/src/main/res/drawable-xxhdpi/default_check.png
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/drawable-xxhdpi/default_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/multi-image-selector/src/main/res/drawable-xxhdpi/default_error.png
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/drawable-xxhdpi/text_indicator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/multi-image-selector/src/main/res/drawable-xxhdpi/text_indicator.png
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/drawable/action_btn.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 | -
12 |
13 |
14 |
15 |
16 |
17 |
18 | -
19 |
20 |
21 |
22 |
23 |
24 |
25 | -
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/layout-v14/fragment_multi_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
26 |
27 |
44 |
45 |
51 |
52 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/layout/activity_default.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
11 |
12 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/layout/cmp_customer_actionbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
24 |
25 |
42 |
43 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/layout/fragment_multi_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
25 |
26 |
42 |
43 |
49 |
50 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/layout/list_item_camera.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
16 |
17 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/layout/list_item_folder.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
21 |
22 |
31 |
32 |
39 |
40 |
49 |
50 |
60 |
61 |
62 |
63 |
73 |
74 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/layout/list_item_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
18 |
19 |
27 |
28 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/values-sw360dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 96dp
4 | 2dp
5 | 72dp
6 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/values-sw480dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 100dp
4 | 2dp
5 | 72dp
6 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/values-sw720dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 120dp
4 | 3dp
5 | 82dp
6 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/values-zh/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 多图选择器
3 | 所有照片
4 | 预览
5 | 没有系统相机
6 | 已经达到最高选择数量
7 | 完成
8 | 张
9 | 拍摄照片
10 |
11 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 120dp
4 | 2dp
5 | 72dp
6 |
--------------------------------------------------------------------------------
/multi-image-selector/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | multi-image-selector
3 | All Images
4 | Preview
5 | No system camera found
6 | Select images amount is limit
7 | Done
8 | Shot
9 | Take photo
10 |
11 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maxiee/HeartBeat/8e61b4929450c596a21c5df2c4545c74d9b095e3/screenshot.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':multi-image-selector'
2 |
--------------------------------------------------------------------------------