diff --git a/.travis.yml b/.travis.yml index 99ffdb213d..de43042784 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,10 +18,10 @@ android: - tools # The BuildTools version used by your project - - build-tools-23.0.2 + - build-tools-24.0.2 # The SDK version used to compile your project - - android-23 + - android-24 # Additional components #- extra-google-google_play_services diff --git a/README.md b/README.md index bf9f9862f0..6f558f5839 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,11 @@ +[![SLicense](https://img.shields.io/badge/License-GPLv3-red.svg) [![Stories in Ready](https://badge.waffle.io/federicoiosue/Omni-Notes.png?label=ready&title=Ready)](https://waffle.io/federicoiosue/Omni-Notes) -[![Stories in In Progress](https://badge.waffle.io/federicoiosue/Omni-Notes.png?label=In%20Progress&title=In Progress)](https://waffle.io/federicoiosue/Omni-Notes) +[![Stories in In Progress](https://badge.waffle.io/federicoiosue/Omni-Notes.png?label=In%20Progress&title=InProgress)](https://waffle.io/federicoiosue/Omni-Notes) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/omni-notes/localized.png)](https://crowdin.com/project/omni-notes) [![Build Status](https://travis-ci.org/federicoiosue/Omni-Notes.svg?branch=develop)](https://travis-ci.org/federicoiosue/Omni-Notes) [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/federicoiosue/omni-notes/trend.png)](https://bitdeli.com/free "Bitdeli Badge") +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/8ade707d00ef468fa79d3f6b622444b5)](https://www.codacy.com/app/federico-iosue/Omni-Notes?utm_source=github.com&utm_medium=referral&utm_content=federicoiosue/Omni-Notes&utm_campaign=Badge_Grade) + Omni-Notes ========== diff --git a/build.gradle b/build.gradle index 2136150a53..db34b379a8 100644 --- a/build.gradle +++ b/build.gradle @@ -29,6 +29,10 @@ buildscript { configurations.classpath.exclude group: 'com.android.tools.external.lombok' } +plugins { + id "org.sonarqube" version "2.0.1" +} + allprojects { repositories { mavenLocal() @@ -38,9 +42,9 @@ allprojects { } } -apply plugin: "sonar-runner" -sonarRunner { - sonarProperties { +apply plugin: 'org.sonarqube' +sonarqube { + properties { property "sonar.host.url", "http://localhost:9000" property "sonar.analysis.mode", "incremental" property 'sonar.sourceEncoding', 'UTF-8' @@ -49,8 +53,8 @@ sonarRunner { } } subprojects { - sonarRunner { - sonarProperties { + sonarqube { + properties { properties["sonar.sources"] += "omniNotes/src/main/java" } } diff --git a/gradle.properties b/gradle.properties index b2802cb716..607486b229 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,9 +16,9 @@ # MIN_SDK=14 -TARGET_SDK=23 -VERSION_NAME=5.2.17 -VERSION_CODE=227 +TARGET_SDK=24 +VERSION_NAME=6.0 +VERSION_CODE=228 PACKAGE=it.feio.android.omninotes # The following properties are empty defaults to allow build and can EVENTUALLY be overridden to allow: diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 59636a4f2a..18d097241c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,21 @@ -#Mon Sep 05 22:26:56 CEST 2016 +# +# Copyright (C) 2015 Federico Iosue (federico.iosue@gmail.com) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +#Tue Sep 06 19:09:13 CEST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/omniNotes/build.gradle b/omniNotes/build.gradle index 016c2c35fe..d4ea758e24 100644 --- a/omniNotes/build.gradle +++ b/omniNotes/build.gradle @@ -20,8 +20,8 @@ apply plugin: 'me.tatarka.retrolambda' android { - compileSdkVersion 23 - buildToolsVersion "23.0.2" + compileSdkVersion 24 + buildToolsVersion "24.0.2" defaultConfig { applicationId project.PACKAGE minSdkVersion project.MIN_SDK @@ -74,8 +74,8 @@ dependencies { } compile 'com.github.gabrielemariotti.changeloglib:changelog:2.0.0' compile 'be.billington.calendar.recurrencepicker:library:1.1.1' - compile 'com.android.support:appcompat-v7:23.2.1' - compile 'com.android.support:design:23.2.1' + compile 'com.android.support:appcompat-v7:24.2.0' + compile 'com.android.support:design:24.2.0' compile 'de.greenrobot:eventbus:2.4.0' compile 'com.pushbullet:android-extensions:1.0.4@aar' compile 'com.getbase:floatingactionbutton:1.10.1' @@ -103,11 +103,15 @@ dependencies { compile 'com.tbruyelle.rxpermissions:rxpermissions:0.4.2@aar' compile 'org.ocpsoft.prettytime:prettytime:3.2.7.Final' compile 'org.piwik.sdk:piwik-sdk:0.0.4' - compile 'com.github.federicoiosue:SimpleGallery:1.2.0' + compile 'com.github.federicoiosue:simplegallery:2.0.0' compile 'com.github.federicoiosue:Springpad-Importer:1.0.1' - compile 'com.github.federicoiosue:Omni-Notes-Commons:1.1.0' + compile 'com.github.federicoiosue:Omni-Notes-Commons:develop-SNAPSHOT' compile 'com.github.federicoiosue:checklistview:3.1.3' compile 'com.github.federicoiosue:pixlui:2.6' + + compile 'com.android.support:appcompat-v7:24.2.0' + compile 'com.android.support:cardview-v7:24.2.0' + compile 'com.android.support:recyclerview-v7:24.2.0' } android.buildTypes.each { type -> diff --git a/omniNotes/src/androidTest/java/it/feio/android/omninotes/utils/date/DateHelperTest.java b/omniNotes/src/androidTest/java/it/feio/android/omninotes/utils/date/DateHelperTest.java index 4af530c908..83385c7699 100644 --- a/omniNotes/src/androidTest/java/it/feio/android/omninotes/utils/date/DateHelperTest.java +++ b/omniNotes/src/androidTest/java/it/feio/android/omninotes/utils/date/DateHelperTest.java @@ -26,7 +26,7 @@ public class DateHelperTest extends InstrumentationTestCase { - long TEN_MINUTES = 10 * 60 * 1000; + private long TEN_MINUTES = 10 * 60 * 1000; public void testNextReminderFromRecurrenceRule() { diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/BaseActivity.java b/omniNotes/src/main/java/it/feio/android/omninotes/BaseActivity.java index 45b551eadd..2c2c4cece6 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/BaseActivity.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/BaseActivity.java @@ -28,9 +28,11 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.support.design.widget.CollapsingToolbarLayout; import android.support.v4.app.FragmentTransaction; import android.support.v4.content.LocalBroadcastManager; import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.*; import android.widget.EditText; @@ -49,12 +51,12 @@ import java.util.List; @SuppressLint("Registered") -public class BaseActivity extends ActionBarActivity { +public class BaseActivity extends AppCompatActivity { protected final int TRANSITION_VERTICAL = 0; protected final int TRANSITION_HORIZONTAL = 1; - protected SharedPreferences prefs; + public SharedPreferences prefs; protected String navigation; protected String navigationTmp; // used for widget navigation @@ -237,13 +239,19 @@ protected void setActionBarTitle(String title) { int actionBarTitle = Resources.getSystem().getIdentifier("action_bar_title", "id", "android"); android.widget.TextView actionBarTitleView = (android.widget.TextView) getWindow().findViewById(actionBarTitle); Typeface font = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Regular.ttf"); - if (actionBarTitleView != null) { - actionBarTitleView.setTypeface(font); - } + //if (actionBarTitleView != null) { + // actionBarTitleView.setTypeface(font); + //} - if (getSupportActionBar() != null) { - getSupportActionBar().setTitle(title); - } +// CollapsingToolbarLayout collapsingToolbar = +// (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar); +// collapsingToolbar.setCollapsedTitleTypeface(font); +// collapsingToolbar.setTitle("Title"); + + + //if (getSupportActionBar() != null) { + // getSupportActionBar().setTitle(title); + //} } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/CategoryActivity.java b/omniNotes/src/main/java/it/feio/android/omninotes/CategoryActivity.java index 93dc6eb26d..930995857b 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/CategoryActivity.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/CategoryActivity.java @@ -47,6 +47,8 @@ import java.util.Calendar; import java.util.Random; +import static java.lang.Integer.parseInt; + public class CategoryActivity extends AppCompatActivity implements ColorChooserDialog.ColorCallback{ @@ -75,7 +77,7 @@ protected void onCreate(Bundle savedInstanceState) { } else { Log.d(Constants.TAG, "Editing category " + category.getName()); } - selectedColor = Integer.parseInt(category.getColor()); + selectedColor = parseInt(category.getColor()); populateViews(); } @@ -109,7 +111,7 @@ private void populateViews() { // Reset picker to saved color String color = category.getColor(); if (color != null && color.length() > 0) { - colorChooser.getDrawable().mutate().setColorFilter(Integer.valueOf(color), PorterDuff.Mode.SRC_ATOP); + colorChooser.getDrawable().mutate().setColorFilter(parseInt(color), PorterDuff.Mode.SRC_ATOP); } deleteBtn.setVisibility(View.VISIBLE); } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/DetailFragment.java b/omniNotes/src/main/java/it/feio/android/omninotes/DetailFragment.java index a063be556f..c6af111619 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/DetailFragment.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/DetailFragment.java @@ -31,6 +31,7 @@ import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.Point; +import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.location.Location; @@ -44,31 +45,59 @@ import android.os.Handler; import android.provider.MediaStore; import android.support.annotation.Nullable; +import android.support.design.widget.AppBarLayout; +import android.support.design.widget.CollapsingToolbarLayout; import android.support.v4.app.FragmentTransaction; import android.support.v4.util.Pair; import android.support.v4.view.MenuItemCompat; import android.support.v4.widget.DrawerLayout; +import android.support.v4.widget.NestedScrollView; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.util.DisplayMetrics; import android.util.Log; -import android.view.*; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; -import android.view.ViewTreeObserver.OnGlobalLayoutListener; +import android.view.ViewGroup; +import android.view.ViewStub; +import android.view.ViewTreeObserver; +import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationUtils; -import android.widget.*; -import butterknife.Bind; -import butterknife.ButterKnife; +import android.view.animation.Transformation; +import android.widget.AutoCompleteTextView; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.PopupWindow; +import android.widget.Toast; + import com.afollestad.materialdialogs.DialogAction; import com.afollestad.materialdialogs.MaterialDialog; import com.bumptech.glide.load.resource.bitmap.GlideBitmapDrawable; import com.neopixl.pixlui.components.edittext.EditText; import com.neopixl.pixlui.components.textview.TextView; import com.pushbullet.android.extension.MessagingExtension; + +import org.apache.commons.lang.StringUtils; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.List; + +import butterknife.Bind; +import butterknife.ButterKnife; import de.greenrobot.event.EventBus; import de.keyboardsurfer.android.widget.crouton.Style; import it.feio.android.checklistview.exceptions.ViewNotSupportedException; @@ -84,9 +113,14 @@ import it.feio.android.omninotes.async.notes.SaveNoteTask; import it.feio.android.omninotes.db.DbHelper; import it.feio.android.omninotes.helpers.AnalyticsHelper; +import it.feio.android.omninotes.helpers.AttachmentsHelper; import it.feio.android.omninotes.helpers.PermissionsHelper; import it.feio.android.omninotes.helpers.date.DateHelper; -import it.feio.android.omninotes.models.*; +import it.feio.android.omninotes.models.Attachment; +import it.feio.android.omninotes.models.Category; +import it.feio.android.omninotes.models.Note; +import it.feio.android.omninotes.models.ONStyle; +import it.feio.android.omninotes.models.Tag; import it.feio.android.omninotes.models.adapters.AttachmentAdapter; import it.feio.android.omninotes.models.adapters.NavDrawerCategoryAdapter; import it.feio.android.omninotes.models.adapters.PlacesAutoCompleteAdapter; @@ -95,26 +129,30 @@ import it.feio.android.omninotes.models.listeners.OnNoteSaved; import it.feio.android.omninotes.models.listeners.OnReminderPickedListener; import it.feio.android.omninotes.models.views.ExpandableHeightGridView; -import it.feio.android.omninotes.utils.*; +import it.feio.android.omninotes.utils.AlphaManager; +import it.feio.android.omninotes.utils.ConnectionManager; +import it.feio.android.omninotes.utils.Constants; import it.feio.android.omninotes.utils.Display; +import it.feio.android.omninotes.utils.FileHelper; +import it.feio.android.omninotes.utils.Fonts; +import it.feio.android.omninotes.utils.GeocodeHelper; +import it.feio.android.omninotes.utils.IntentChecker; +import it.feio.android.omninotes.utils.KeyboardUtils; +import it.feio.android.omninotes.utils.ReminderHelper; +import it.feio.android.omninotes.utils.ShortcutHelper; +import it.feio.android.omninotes.utils.StorageHelper; +import it.feio.android.omninotes.utils.TagsHelper; +import it.feio.android.omninotes.utils.TextHelper; import it.feio.android.omninotes.utils.date.DateUtils; import it.feio.android.omninotes.utils.date.ReminderPickers; import it.feio.android.pixlui.links.TextLinkClickListener; -import org.apache.commons.lang.StringUtils; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.List; import static com.nineoldandroids.view.ViewPropertyAnimator.animate; +import static java.lang.Integer.parseInt; public class DetailFragment extends BaseFragment implements OnReminderPickedListener, OnTouchListener, - OnGlobalLayoutListener, OnAttachingFileListener, TextWatcher, CheckListChangedListener, OnNoteSaved, - OnGeoUtilResultListener { + OnAttachingFileListener, TextWatcher, CheckListChangedListener, OnNoteSaved, OnGeoUtilResultListener { private static final int TAKE_PHOTO = 1; private static final int TAKE_VIDEO = 2; @@ -124,45 +162,26 @@ public class DetailFragment extends BaseFragment implements OnReminderPickedList private static final int DETAIL = 6; private static final int FILES = 7; - @Bind(R.id.detail_root) - ViewGroup root; - @Bind(R.id.detail_title) + @Bind(R.id.detail_root) ViewGroup root; + @Bind(R.id.detail_content) EditText content; + @Bind(R.id.detail_attachments_above) ViewStub attachmentsAbove; + @Bind(R.id.detail_attachments_below) ViewStub attachmentsBelow; + @Nullable @Bind(R.id.gridview) ExpandableHeightGridView mGridView; + @Bind(R.id.location) TextView locationTextView; + @Bind(R.id.reminder_layout) LinearLayout reminder_layout; + @Bind(R.id.reminder_icon) ImageView reminderIcon; + @Bind(R.id.datetime) TextView datetime; + @Bind(R.id.content_wrapper) NestedScrollView scrollView; + @Bind(R.id.snackbar_placeholder) View snackBarPlaceholder; + @Bind(R.id.bottomSpacer) View bottomSpacer; + + LinearLayout titleWrapperView; EditText title; - @Bind(R.id.detail_content) - EditText content; - @Bind(R.id.detail_attachments_above) - ViewStub attachmentsAbove; - @Bind(R.id.detail_attachments_below) - ViewStub attachmentsBelow; - @Nullable - @Bind(R.id.gridview) - ExpandableHeightGridView mGridView; - @Bind(R.id.location) - TextView locationTextView; - @Bind(R.id.detail_timestamps) + TextView detailTitleText; View timestampsView; - @Bind(R.id.reminder_layout) - LinearLayout reminder_layout; - @Bind(R.id.reminder_icon) - ImageView reminderIcon; - @Bind(R.id.datetime) - TextView datetime; - @Bind(R.id.detail_tile_card) - View titleCardView; - @Bind(R.id.content_wrapper) - ScrollView scrollView; - @Bind(R.id.creation) TextView creationTextView; - @Bind(R.id.last_modification) TextView lastModificationTextView; - @Bind(R.id.title_wrapper) - View titleWrapperView; - @Bind(R.id.tag_marker) - View tagMarkerView; - @Bind(R.id.detail_wrapper) - ViewManager detailWrapperView; - @Bind(R.id.snackbar_placeholder) - View snackBarPlaceholder; + View detailLineSeperator; public OnDateSetListener onDateSetListener; public OnTimeSetListener onTimeSetListener; @@ -174,6 +193,7 @@ public class DetailFragment extends BaseFragment implements OnReminderPickedList private Note note; private Note noteTmp; private Note noteOriginal; + // Audio recording private String recordName; private MediaRecorder mRecorder = null; @@ -182,9 +202,11 @@ public class DetailFragment extends BaseFragment implements OnReminderPickedList private View isPlayingView = null; private Bitmap recordingBitmap; private ChecklistManager mChecklistManager; + // Values to print result private String exitMessage; private Style exitCroutonStyle = ONStyle.CONFIRM; + // Flag to check if after editing it will return to ListActivity or not // and in the last case a Toast will be shown instead than Crouton private boolean afterSavedReturnsToList = true; @@ -204,8 +226,10 @@ public class DetailFragment extends BaseFragment implements OnReminderPickedList private MainActivity mainActivity; private boolean activityPausing; + private static boolean goneHome; - @Override + + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mFragment = this; @@ -231,11 +255,6 @@ public void onStop() { @Override public void onResume() { super.onResume(); - // Adding a layout observer to perform calculus when showing keyboard - if (root != null) { - root.getViewTreeObserver().addOnGlobalLayoutListener(this); - } - activityPausing = false; } @@ -244,7 +263,79 @@ public void onResume() { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_detail, container, false); ButterKnife.bind(this, view); - return view; + + MainActivity activity = (MainActivity) getActivity(); + ViewGroup collapsingToolbar = ButterKnife.findById(activity.outerToolbar, R.id.collapsing_toolbar); + + + View toolbarView = ButterKnife.findById(collapsingToolbar, R.id.title_wrapper); + if (toolbarView == null ) { + toolbarView = inflater.inflate(R.layout.fragment_detail_toolbar, collapsingToolbar, true); + } + + titleWrapperView = ButterKnife.findById(toolbarView, R.id.title_wrapper); + title = ButterKnife.findById(toolbarView, R.id.detail_title); + detailTitleText = ButterKnife.findById(toolbarView, R.id.detail_title_text); + timestampsView = ButterKnife.findById(toolbarView, R.id.detail_timestamps); + creationTextView = ButterKnife.findById(toolbarView, R.id.creation); + lastModificationTextView = ButterKnife.findById(toolbarView, R.id.last_modification); + detailLineSeperator = ButterKnife.findById(toolbarView, R.id.detail_line_seperator); + + AppBarLayout appBarLayout = activity.outerToolbar; + appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { + @Override + public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { + float v = 1.0f + (float) verticalOffset / appBarLayout.getTotalScrollRange(); + if (verticalOffset == 0.0f) { + v = 1.0f; + } + + if (DetailFragment.goneHome && v <= 0.0f) { + titleWrapperView.setVisibility(View.GONE); + } + + detailTitleText.setAlpha(v); + detailLineSeperator.setAlpha(v); + creationTextView.setAlpha(v); + lastModificationTextView.setAlpha(v); + } + }); + + + // set a global layout listener which will be called when the layout pass is completed and the view is drawn + creationTextView.getViewTreeObserver().addOnGlobalLayoutListener( + new ViewTreeObserver.OnGlobalLayoutListener() { + public void onGlobalLayout() { + //Remove the listener before proceeding + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + view.getViewTreeObserver().removeOnGlobalLayoutListener(this); + } else { + view.getViewTreeObserver().removeGlobalOnLayoutListener(this); + } + + ViewGroup collapsingToolbar = ButterKnife.findById(mainActivity.outerToolbar, R.id.collapsing_toolbar); + + // measure your views here + Rect titleRect = new Rect(); + title.getGlobalVisibleRect(titleRect); + + Rect toolbarRect = new Rect(); + collapsingToolbar.getGlobalVisibleRect(toolbarRect); + + float titleHeight = titleRect.bottom - titleRect.top; + float toolbarHeight = toolbarRect.bottom - toolbarRect.top; + float navHeight = Display.getNavigationBarHeightStandard(getContext()); + float parallaxMultiplier = + 1.0f - (titleRect.bottom - (titleHeight / 2.0f) - DensityUtil.dpToPx(2, getContext())) / (toolbarRect.bottom); + + CollapsingToolbarLayout.LayoutParams titleLayoutParams = + (CollapsingToolbarLayout.LayoutParams) titleWrapperView.getLayoutParams(); + titleLayoutParams.setParallaxMultiplier(parallaxMultiplier); + } + }); + + + return view; } @@ -291,6 +382,28 @@ public void onActivityCreated(Bundle savedInstanceState) { setHasOptionsMenu(true); setRetainInstance(false); + + if (mainActivity != null && mainActivity.getSupportActionBar() != null) { + mainActivity.getSupportActionBar().setElevation(0); + } + +// ViewGroup collapsingToolbar = ButterKnife.findById(mainActivity.outerToolbar, R.id.collapsing_toolbar); +// View toolbarView = ButterKnife.findById(collapsingToolbar, R.id.title_wrapper); +// mainActivity.outerToolbar.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); +// android.support.v7.widget.Toolbar innerToolbar = ButterKnife.findById(toolbarView, R.id.toolbar); +// float titleHeight = titleWrapperView.getMeasuredHeight(); +// float toolbarHeight = innerToolbar.getHeight(); // - getStatusBarHeight(); +// +// CollapsingToolbarLayout.LayoutParams titleLayoutParams = +// (CollapsingToolbarLayout.LayoutParams) titleWrapperView.getLayoutParams(); +// titleLayoutParams.setParallaxMultiplier(toolbarHeight / titleHeight); +// +// Log.e("Bla", String.valueOf(titleHeight) + " / " + toolbarHeight + " = " + (toolbarHeight / titleHeight)); + + + titleWrapperView.setVisibility(View.VISIBLE); + DetailFragment.goneHome = false; + mainActivity.outerToolbar.setExpanded(true, true); } @@ -327,15 +440,6 @@ public void onPause() { mRecorder = null; } - // Unregistering layout observer - if (root != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - root.getViewTreeObserver().removeOnGlobalLayoutListener(this); - } else { - root.getViewTreeObserver().removeGlobalOnLayoutListener(this); - } - } - // Closes keyboard on exit if (toggleChecklistView != null) { KeyboardUtils.hideKeyboard(toggleChecklistView); @@ -541,14 +645,14 @@ private void initViewFooter() { // Footer dates of creation... String creation = DateHelper.getFormattedDate(noteTmp.getCreation(), prefs.getBoolean(Constants .PREF_PRETTIFIED_DATES, true)); - creationTextView.append(creation.length() > 0 ? getString(R.string.creation) + " " + creation : ""); + creationTextView.setText(creation.length() > 0 ? getString(R.string.creation) + " " + creation : ""); if (creationTextView.getText().length() == 0) creationTextView.setVisibility(View.GONE); // ... and last modification String lastModification = DateHelper.getFormattedDate(noteTmp.getLastModification(), prefs.getBoolean(Constants .PREF_PRETTIFIED_DATES, true)); - lastModificationTextView.append(lastModification.length() > 0 ? getString(R.string.last_update) + " " + + lastModificationTextView.setText(lastModification.length() > 0 ? getString(R.string.last_update) + " " + lastModification : ""); if (lastModificationTextView.getText().length() == 0) lastModificationTextView.setVisibility(View.GONE); @@ -569,7 +673,6 @@ private void initViewReminder() { onTimeSetListener = reminderPicker; }); - reminder_layout.setOnLongClickListener(v -> { MaterialDialog dialog = new MaterialDialog.Builder(mainActivity) .content(R.string.remove_reminder) @@ -593,15 +696,14 @@ public void onPositive(MaterialDialog materialDialog) { datetime.setText(reminderString); } - // Timestamps view // Bottom padding set for translucent navbar in Kitkat if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { int navBarHeight = Display.getNavigationBarHeightKitkat(mainActivity); int negativePadding = navBarHeight >= 27 * 3 ? -27 : 0; - int timestampsViewPaddingBottom = navBarHeight > 0 ? navBarHeight + negativePadding : timestampsView + int bottomSpacerViewPaddingBottom = navBarHeight > 0 ? navBarHeight + negativePadding : bottomSpacer .getPaddingBottom(); - timestampsView.setPadding(timestampsView.getPaddingStart(), timestampsView.getPaddingTop(), - timestampsView.getPaddingEnd(), timestampsViewPaddingBottom); + bottomSpacer.setPadding(bottomSpacer.getPaddingStart(), bottomSpacer.getPaddingTop(), + bottomSpacer.getPaddingEnd(), bottomSpacerViewPaddingBottom); } } @@ -667,7 +769,7 @@ private void getLocation(OnGeoUtilResultListener onGeoUtilResultListener) { private void initViewAttachments() { // Attachments position based on preferences - if (prefs.getBoolean(Constants.PREF_ATTANCHEMENTS_ON_BOTTOM, false)) { + if (prefs.getBoolean(Constants.PREF_ATTANCHEMENTS_ON_BOTTOM, true)) { attachmentsBelow.inflate(); } else { attachmentsAbove.inflate(); @@ -735,17 +837,15 @@ private void initViewAttachments() { }); mGridView.setOnItemLongClickListener((parent, v, position, id) -> { - // To avoid deleting audio attachment during playback if (mPlayer != null) return false; - List items = Arrays.asList(getResources().getStringArray(R.array.attachments_actions)); if (!Constants.MIME_TYPE_SKETCH.equals(mAttachmentAdapter.getItem(position).getMime_type())) { items = items.subList(0, items.size() - 1); } - + Attachment attachment = mAttachmentAdapter.getItem(position); new MaterialDialog.Builder(mainActivity) - .title(mAttachmentAdapter.getItem(position).getName()) + .title(attachment.getName() + " (" + AttachmentsHelper.getSize(attachment) + ")") .items(items.toArray(new String[items.size()])) .itemsCallback((materialDialog, view, i, charSequence) -> performAttachmentAction(position, i)) @@ -839,7 +939,7 @@ private void initViewContent() { /** * Force focus and shows soft keyboard. Only happens if it's a new note, without shared content. - * {@link showKeyboard} is used to check if the note is created from shared content. + * showKeyboard is used to check if the note is created from shared content. */ private void requestFocus(final EditText view) { if (note.get_id() == null && !noteTmp.isChanged(note) && showKeyboard) { @@ -864,13 +964,13 @@ private void setTagMarkerColor(Category tag) { target.add(titleWrapperView); target.add(scrollView); } else { - target.add(tagMarkerView); + //target.add(tagMarkerView); } // Coloring the target if (tag != null && tag.getColor() != null) { for (View view : target) { - view.setBackgroundColor(Integer.parseInt(tag.getColor())); + view.setBackgroundColor(parseInt(tag.getColor())); } } else { for (View view : target) { @@ -960,6 +1060,15 @@ public void afterTextChanged(Editable s) { }); } + public int getStatusBarHeight() { + int result = 0; + int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + result = getResources().getDimensionPixelSize(resourceId); + } + return result; + } + @Override public void onLocationRetrieved(Location location) { @@ -1085,9 +1194,67 @@ public boolean goHome() { } } + //collapse(titleWrapperView); + DetailFragment.goneHome = true; + mainActivity.outerToolbar.setExpanded(false, true); + return true; } + public static void collapse(final View v) { + final int initialHeight = v.getMeasuredHeight(); + + Animation a = new Animation() + { + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + if(interpolatedTime == 1){ + v.setVisibility(View.GONE); + }else{ + v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime); + v.requestLayout(); + } + } + + @Override + public boolean willChangeBounds() { + return true; + } + }; + + // 5dp/ms + a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density) * 5); + v.startAnimation(a); + } + + public static void expand(final View v) { + v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + final int targetHeight = v.getMeasuredHeight(); + + // Older versions of android (pre API 21) cancel animations for views with a height of 0. + v.getLayoutParams().height = 1; + v.setVisibility(View.VISIBLE); + Animation a = new Animation() + { + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + v.getLayoutParams().height = interpolatedTime == 1 + ? ViewGroup.LayoutParams.WRAP_CONTENT + : (int)(targetHeight * interpolatedTime); + v.requestLayout(); + } + + @Override + public boolean willChangeBounds() { + return true; + } + }; + + // 3dp/ms + a.setDuration((int)(targetHeight / v.getContext().getResources().getDisplayMetrics().density) * 3); + v.startAnimation(a); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { @@ -1137,6 +1304,7 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.menu_delete: deleteNote(); break; + default: Log.w(Constants.TAG, "Invalid menu option selected"); } AnalyticsHelper.trackActionFromResourceId(getActivity(), item.getItemId()); @@ -1215,7 +1383,7 @@ private void toggleChecklist2(final boolean keepChecked, final boolean showCheck .newEntryHint(getString(R.string.checklist_item_hint)) .keepChecked(keepChecked) .undoBarContainerView(scrollView) - .moveCheckedOnBottom(Integer.valueOf(prefs.getString("settings_checked_items_behavior", String.valueOf + .moveCheckedOnBottom(parseInt(prefs.getString("settings_checked_items_behavior", String.valueOf (it.feio.android.checklistview.Settings.CHECKED_HOLD)))); // Links parsing options @@ -1386,7 +1554,7 @@ private void takeVideo() { } String maxVideoSizeStr = "".equals(prefs.getString("settings_max_video_size", "")) ? "0" : prefs.getString("settings_max_video_size", ""); - int maxVideoSize = Integer.parseInt(maxVideoSizeStr); + int maxVideoSize = parseInt(maxVideoSizeStr); takeVideoIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, Long.valueOf(maxVideoSize * 1024 * 1024)); startActivityForResult(takeVideoIntent, TAKE_VIDEO); } @@ -1465,6 +1633,8 @@ public void onActivityResult(int requestCode, int resultCode, Intent intent) { case DETAIL: mainActivity.showMessage(R.string.note_updated, ONStyle.CONFIRM); break; + default: + Log.e(Constants.TAG, "Wrong element choosen: " + requestCode); } } } @@ -1902,7 +2072,8 @@ private void stopRecording() { } - private void fade(final View v, boolean fadeIn) { + @SuppressWarnings("ResourceType") + private void fade(final View v, boolean fadeIn) { int anim = R.animator.fade_out_support; int visibilityTemp = View.GONE; @@ -1921,13 +2092,13 @@ private void fade(final View v, boolean fadeIn) { mAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { - // Nothind to do + // Nothing to do } @Override public void onAnimationRepeat(Animation animation) { - // Nothind to do + // Nothing to do } @@ -2056,50 +2227,12 @@ public boolean onTouch(View v, MotionEvent event) { } } break; - } - - return true; - } - - - @Override - public void onGlobalLayout() { - int screenHeight = Display.getUsableSize(mainActivity).y; - int navBarOffset = Display.orientationLandscape(mainActivity) ? 0 : DensityUtil.pxToDp(Display - .getNavigationBarHeight(mainActivity.getWindow().getDecorView()), mainActivity); - int heightDiff = screenHeight - Display.getVisibleSize(mainActivity).y + navBarOffset; - boolean keyboardVisible = heightDiff > 150; - if (keyboardVisible && keyboardPlaceholder == null) { - shrinkLayouts(heightDiff); - } else if (!keyboardVisible && keyboardPlaceholder != null) { - restoreLayouts(); - } - } - - private void shrinkLayouts(int heightDiff) { - detailWrapperView.removeView(timestampsView); - keyboardPlaceholder = new View(mainActivity); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - if (!(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Display.orientationLandscape(mainActivity) - )) { - root.addView(keyboardPlaceholder, LinearLayout.LayoutParams.MATCH_PARENT, heightDiff); - } + default: + Log.e(Constants.TAG, "Wrong element choosen: " + event.getAction()); } - } - - private void restoreLayouts() { - if (root != null) { - ViewGroup wrapper = (ViewGroup) root.findViewById(R.id.detail_wrapper); - if (root.indexOfChild(keyboardPlaceholder) != -1) { - root.removeView(keyboardPlaceholder); - } - keyboardPlaceholder = null; - if (wrapper.indexOfChild(timestampsView) == -1) { - wrapper.addView(timestampsView); - } - } + return true; } @@ -2376,6 +2509,8 @@ public void onClick(View v) { null, 0); attachmentDialog.dismiss(); break; + default: + Log.e(Constants.TAG, "Wrong element choosen: " + v.getId()); } } } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/GalleryActivity.java b/omniNotes/src/main/java/it/feio/android/omninotes/GalleryActivity.java index a9edd4651c..e14de263fb 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/GalleryActivity.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/GalleryActivity.java @@ -66,10 +66,6 @@ public class GalleryActivity extends ActionBarActivity { */ private static final boolean TOGGLE_ON_CLICK = true; - /** - * The flags to pass to {@link SystemUiHider#getInstance}. - */ - @Bind(R.id.gallery_root) InterceptorFrameLayout galleryRootView; @Bind(R.id.fullscreen_content) GalleryViewPager mViewPager; @@ -138,10 +134,9 @@ private void initData() { images = getIntent().getParcelableArrayListExtra(Constants.GALLERY_IMAGES); int clickedImage = getIntent().getIntExtra(Constants.GALLERY_CLICKED_IMAGE, 0); - ArrayList imagesPaths = new ArrayList<>(); + ArrayList imagesPaths = new ArrayList<>(); for (Attachment mAttachment : images) { - Uri uri = mAttachment.getUri(); - imagesPaths.add(FileHelper.getPath(this, uri)); + imagesPaths.add(mAttachment.getUri()); } GalleryPagerAdapter pagerAdapter = new GalleryPagerAdapter(this, imagesPaths); @@ -165,14 +160,14 @@ public boolean onOptionsItemSelected(MenuItem item) { case android.R.id.home: onBackPressed(); break; - case R.id.menu_gallery_share: { + case R.id.menu_gallery_share: shareMedia(); break; - } - case R.id.menu_gallery: { + case R.id.menu_gallery: viewMedia(); break; - } + default: + Log.e(Constants.TAG, "Wrong element choosen: " + item.getItemId()); } return super.onOptionsItemSelected(item); } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/ListFragment.java b/omniNotes/src/main/java/it/feio/android/omninotes/ListFragment.java index 9fe1c54dc8..e942c24583 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/ListFragment.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/ListFragment.java @@ -33,8 +33,11 @@ import android.support.v4.view.GravityCompat; import android.support.v4.view.MenuItemCompat; import android.support.v7.view.ActionMode; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SearchView; import android.support.v7.widget.SearchView.OnQueryTextListener; +import android.support.v7.widget.helper.ItemTouchHelper; import android.text.Html; import android.text.TextUtils; import android.util.Log; @@ -47,7 +50,6 @@ import butterknife.ButterKnife; import com.afollestad.materialdialogs.MaterialDialog; import com.neopixl.pixlui.components.textview.TextView; -import com.nhaarman.listviewanimations.itemmanipulation.DynamicListView; import com.pnikosis.materialishprogress.ProgressWheel; import de.greenrobot.event.EventBus; import de.keyboardsurfer.android.widget.crouton.Crouton; @@ -65,10 +67,14 @@ import it.feio.android.omninotes.models.adapters.NavDrawerCategoryAdapter; import it.feio.android.omninotes.models.adapters.NoteAdapter; import it.feio.android.omninotes.models.holders.NoteViewHolder; -import it.feio.android.omninotes.models.listeners.OnPermissionRequestedListener; import it.feio.android.omninotes.models.listeners.OnViewTouchedListener; +import it.feio.android.omninotes.models.manager.ExStaggeredGridLayoutManager; +import it.feio.android.omninotes.models.misc.HeaderSpanSizeLookup; +import it.feio.android.omninotes.models.misc.ItemClickSupport; +import it.feio.android.omninotes.models.views.ExRecyclerView; import it.feio.android.omninotes.models.views.Fab; import it.feio.android.omninotes.models.views.InterceptorLinearLayout; +import it.feio.android.omninotes.models.views.NoteDecoration; import it.feio.android.omninotes.utils.*; import it.feio.android.omninotes.utils.Display; import it.feio.android.pixlui.links.UrlCompleter; @@ -87,11 +93,11 @@ public class ListFragment extends BaseFragment implements OnViewTouchedListener, private static final int REQUEST_CODE_ADD_ALARMS = 3; @Bind(R.id.list_root) InterceptorLinearLayout listRoot; - @Bind(R.id.list) DynamicListView list; + @Bind(R.id.list) ExRecyclerView list; @Bind(R.id.search_layout) View searchLayout; @Bind(R.id.search_query) android.widget.TextView searchQueryView; @Bind(R.id.search_cancel) ImageView searchCancel; - @Bind(R.id.empty_list) TextView empyListItem; + @Bind(R.id.empty_list) TextView emptyListItem; @Bind(R.id.expanded_image) ImageView expandedImageView; @Bind(R.id.fab) View fabView; @Bind(R.id.undobar) View undoBarView; @@ -119,7 +125,7 @@ public class ListFragment extends BaseFragment implements OnViewTouchedListener, private boolean undoArchive = false; private boolean undoCategorize = false; private Category undoCategorizeCategory = null; - private SortedMap undoNotesMap = new TreeMap<>(); + private TreeMap undoNotesMap = new TreeMap<>(); // Used to remember removed categories from notes private Map undoCategoryMap = new HashMap<>(); // Used to remember archived state from notes @@ -174,6 +180,19 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa } View view = inflater.inflate(R.layout.fragment_list, container, false); ButterKnife.bind(this, view); + + list.setHasFixedSize(true); + ExStaggeredGridLayoutManager layoutManager = new ExStaggeredGridLayoutManager(2, + ExStaggeredGridLayoutManager.VERTICAL); + list.setLayoutManager(layoutManager); + + int spacingInPixels = getResources().getDimensionPixelSize(R.dimen.spacing); + list.addItemDecoration(new NoteDecoration(spacingInPixels)); + + RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator(); + itemAnimator.setAddDuration(1000); + itemAnimator.setRemoveDuration(1000); + list.setItemAnimator(itemAnimator); return view; } @@ -277,10 +296,10 @@ private void initTitle() { * Starts a little animation on Mr.Jingles! */ private void initEasterEgg() { - empyListItem.setOnClickListener(v -> { + emptyListItem.setOnClickListener(v -> { if (jinglesAnimation == null) { - jinglesAnimation = (AnimationDrawable) empyListItem.getCompoundDrawables()[1]; - empyListItem.post(() -> { + jinglesAnimation = (AnimationDrawable) emptyListItem.getCompoundDrawables()[1]; + emptyListItem.post(() -> { if (jinglesAnimation != null) jinglesAnimation.start(); }); } else { @@ -294,7 +313,7 @@ private void stopJingles() { if (jinglesAnimation != null) { jinglesAnimation.stop(); jinglesAnimation = null; - empyListItem.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.jingles_animation, 0, 0); + emptyListItem.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.jingles_animation, 0, 0); } } @@ -309,7 +328,6 @@ public void onPause() { closeFab(); if (!keepActionMode) { commitPending(); - list.clearChoices(); if (getActionMode() != null) { getActionMode().finish(); } @@ -330,9 +348,13 @@ public void onSaveInstanceState(Bundle outState) { private void refreshListScrollPosition() { if (list != null) { - listViewPosition = list.getFirstVisiblePosition(); - View v = list.getChildAt(0); - listViewPositionOffset = (v == null) ? (int) getResources().getDimension(R.dimen.vertical_margin) : v.getTop(); + ExStaggeredGridLayoutManager layoutManager = ((ExStaggeredGridLayoutManager)list.getLayoutManager()); + int[] firstVisibleItems = null; + firstVisibleItems = layoutManager.findFirstVisibleItemPositions(firstVisibleItems); + if (firstVisibleItems != null && firstVisibleItems.length > 0) { + View v = list.getChildAt(firstVisibleItems[0]); + listViewPositionOffset = (v == null) ? (int) getResources().getDimension(R.dimen.vertical_margin) : v.getTop(); + } } } @@ -368,16 +390,20 @@ public void onDestroyActionMode(ActionMode mode) { // deselected/unchecked. for (int i = 0; i < listAdapter.getSelectedItems().size(); i++) { int key = listAdapter.getSelectedItems().keyAt(i); - View v = list.getChildAt(key - list.getFirstVisiblePosition()); - if (listAdapter.getCount() > key && listAdapter.getItem(key) != null && v != null) { - listAdapter.restoreDrawable(listAdapter.getItem(key), v.findViewById(R.id.card_layout)); + ExStaggeredGridLayoutManager layoutManager = ((ExStaggeredGridLayoutManager)list.getLayoutManager()); + int[] firstVisibleItems = null; + firstVisibleItems = layoutManager.findFirstVisibleItemPositions(firstVisibleItems); + if (firstVisibleItems != null && firstVisibleItems.length > 0) { + View v = list.getChildAt(key - firstVisibleItems[0]); + if (listAdapter.getInnerItemCount() > key && listAdapter.getItem(key) != null && v != null) { + listAdapter.restoreDrawable(listAdapter.getItem(key), v.findViewById(R.id.card_layout)); + } } } // Clears data structures selectedNotes.clear(); listAdapter.clearSelectedItems(); - list.clearChoices(); fab.setAllowed(isFabAllowed(true)); if (undoNotesMap.size() == 0) { @@ -450,43 +476,41 @@ private void toggleListViewItem(View view, int position) { * Notes list initialization. Data, actions and callback are defined here. */ private void initListView() { - list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); - list.setItemsCanFocus(false); - - // If device runs KitKat a footer is added to list to avoid - // navigation bar transparency covering items - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - int navBarHeight = Display.getNavigationBarHeightKitkat(mainActivity); - listFooter = new TextView(mainActivity.getApplicationContext()); - listFooter.setHeight(navBarHeight); - // To avoid useless events on footer - listFooter.setOnClickListener(null); - list.addFooterView(listFooter); - } - - // Note long click to start CAB mode - list.setOnItemLongClickListener((arg0, view, position, arg3) -> { - if (view.equals(listFooter)) return true; - if (getActionMode() != null) { - return false; - } - // Start the CAB using the ActionMode.Callback defined above - mainActivity.startSupportActionMode(new ModeCallback()); - toggleListViewItem(view, position); - setCabTitle(); - return true; - }); - - // Note single click listener managed by the activity itself - list.setOnItemClickListener((arg0, view, position, arg3) -> { - if (view.equals(listFooter)) return; - if (getActionMode() == null) { - editNote(listAdapter.getItem(position), view); - return; - } - // If in CAB mode - toggleListViewItem(view, position); - setCabTitle(); + // list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); // TODO jd + // list.setItemsCanFocus(false); + + ItemClickSupport.addTo(list) + // Note single click listener managed by the activity itself + .setOnItemClickListener(new ItemClickSupport.OnItemClickListener() { + @Override + public void onItemClicked(RecyclerView recyclerView, int position, View view) { + if (view.equals(listFooter)) { + return; + } + if (getActionMode() == null) { + editNote(listAdapter.getItem(position), view); + return; + } + // If in CAB mode + toggleListViewItem(view, position); + setCabTitle(); + } + // Note long click to start CAB mode + }).setOnItemLongClickListener(new ItemClickSupport.OnItemLongClickListener() { + @Override + public boolean onItemLongClicked(RecyclerView recyclerView, int position, View view) { + if (view.equals(listFooter)) { + return false; + } + if (getActionMode() != null) { + return false; + } + // Start the CAB using the ActionMode.Callback defined above + mainActivity.startSupportActionMode(new ModeCallback()); + toggleListViewItem(view, position); + setCabTitle(); + return true; + } }); listRoot.setOnViewTouchedListener(this); @@ -698,7 +722,7 @@ private void setActionItemsVisibility(Menu menu, boolean searchViewHasFocus) { boolean drawerOpen = mainActivity.getDrawerLayout() != null && mainActivity.getDrawerLayout().isDrawerOpen (GravityCompat.START); - boolean expandedView = prefs.getBoolean(Constants.PREF_EXPANDED_VIEW, true); + int viewMode = prefs.getInt(Constants.PREF_VIEW_MODE, Constants.VIEW_MODE_CONTRACTED); int navigation = Navigation.getNavigation(); boolean navigationReminders = navigation == Navigation.REMINDERS; @@ -727,8 +751,9 @@ private void setActionItemsVisibility(Menu menu, boolean searchViewHasFocus) { menu.findItem(R.id.menu_filter_category_remove).setVisible(!drawerOpen && filterArchivedInCategory && navigationCategory && !searchViewHasFocus); menu.findItem(R.id.menu_sort).setVisible(!drawerOpen && !navigationReminders && !searchViewHasFocus); - menu.findItem(R.id.menu_expanded_view).setVisible(!drawerOpen && !expandedView && !searchViewHasFocus); - menu.findItem(R.id.menu_contracted_view).setVisible(!drawerOpen && expandedView && !searchViewHasFocus); + menu.findItem(R.id.menu_expanded_view).setVisible(!drawerOpen && viewMode != Constants.VIEW_MODE_EXPANDED && !searchViewHasFocus); + menu.findItem(R.id.menu_contracted_view).setVisible(!drawerOpen && viewMode != Constants.VIEW_MODE_CONTRACTED && !searchViewHasFocus); + menu.findItem(R.id.menu_grid_view).setVisible(!drawerOpen && viewMode != Constants.VIEW_MODE_GRID && !searchViewHasFocus); menu.findItem(R.id.menu_empty_trash).setVisible(!drawerOpen && navigationTrash); menu.findItem(R.id.menu_tags).setVisible(searchViewHasFocus); } @@ -782,14 +807,19 @@ public boolean performAction(MenuItem item, ActionMode actionMode) { initSortingSubmenu(); break; case R.id.menu_expanded_view: - switchNotesView(); + switchNotesView(Constants.VIEW_MODE_EXPANDED); break; case R.id.menu_contracted_view: - switchNotesView(); + switchNotesView(Constants.VIEW_MODE_CONTRACTED); + break; + case R.id.menu_grid_view: + switchNotesView(Constants.VIEW_MODE_GRID); break; case R.id.menu_empty_trash: emptyTrash(); break; + default: + Log.e(Constants.TAG, "Wrong element choosen: " + item.getItemId()); } } else { switch (item.getItemId()) { @@ -849,9 +879,9 @@ private void addReminders() { } - private void switchNotesView() { - boolean expandedView = prefs.getBoolean(Constants.PREF_EXPANDED_VIEW, true); - prefs.edit().putBoolean(Constants.PREF_EXPANDED_VIEW, !expandedView).commit(); + private void switchNotesView(int menu_grid_view) { + int viewMode = prefs.getInt(Constants.PREF_VIEW_MODE, menu_grid_view); + prefs.edit().putInt(Constants.PREF_VIEW_MODE, menu_grid_view).commit(); // Change list view initNotesList(mainActivity.getIntent()); // Called to switch menu voices @@ -930,10 +960,8 @@ void onActivityResult(int requestCode, final int resultCode, Intent intent) { break; case REQUEST_CODE_ADD_ALARMS: - list.clearChoices(); selectedNotes.clear(); finishActionMode(); - list.invalidateViews(); break; default: @@ -971,7 +999,7 @@ private void emptyTrash() { public void onPositive(MaterialDialog materialDialog) { boolean mustDeleteLockedNotes = false; - for (int i = 0; i < listAdapter.getCount(); i++) { + for (int i = 0; i < listAdapter.getInnerItemCount(); i++) { selectedNotes.add(listAdapter.getItem(i)); mustDeleteLockedNotes = mustDeleteLockedNotes || listAdapter.getItem(i).isLocked(); } @@ -997,7 +1025,10 @@ void initNotesList(Intent intent) { Log.d(Constants.TAG, "initNotesList intent: " + intent.getAction()); progress_wheel.setAlpha(1); - list.setAlpha(0); + + if (list.getAdapter() == null) { + list.setAlpha(0); + } // Search for a tag // A workaround to simplify it's to simulate normal search @@ -1101,28 +1132,56 @@ public void onEvent(CategoriesUpdatedEvent categoriesUpdatedEvent) { public void onEvent(NotesLoadedEvent notesLoadedEvent) { - int layoutSelected = prefs.getBoolean(Constants.PREF_EXPANDED_VIEW, true) ? R.layout.note_layout_expanded - : R.layout.note_layout; - listAdapter = new NoteAdapter(mainActivity, layoutSelected, notesLoadedEvent.notes); + ExStaggeredGridLayoutManager layoutManager = (ExStaggeredGridLayoutManager)list.getLayoutManager(); + + int layoutSelected = R.layout.note_layout; + switch (prefs.getInt(Constants.PREF_VIEW_MODE, Constants.VIEW_MODE_CONTRACTED)) { + case Constants.VIEW_MODE_EXPANDED: + layoutManager.setSpanCount(1); + layoutSelected = R.layout.note_layout_expanded; + break; + case Constants.VIEW_MODE_GRID: + layoutManager.setSpanCount(2); + layoutSelected = R.layout.note_layout_grid; + break; + case Constants.VIEW_MODE_CONTRACTED: + default: + layoutManager.setSpanCount(1); + } View noteLayout = LayoutInflater.from(mainActivity).inflate(layoutSelected, null, false); noteViewHolder = new NoteViewHolder(noteLayout); - if (Navigation.getNavigation() != Navigation.UNCATEGORIZED && prefs.getBoolean(Constants.PREF_ENABLE_SWIPE, + boolean isNewList = false; + if (listAdapter == null || list.getAdapter() == null) { + listAdapter = new NoteAdapter(mainActivity, layoutSelected, notesLoadedEvent.notes); + list.setAdapter(listAdapter); + isNewList = true; + } else { + listAdapter.setLayout(layoutSelected); + listAdapter.setNotes(notesLoadedEvent.notes); + } + + layoutManager.setSpanSizeLookup( + new HeaderSpanSizeLookup(listAdapter, layoutManager.getSpanCount())); + + + + if (Navigation.getNavigation() != Navigation.UNCATEGORIZED && prefs.getBoolean(Constants.PREF_ENABLE_SWIPE, true)) { - list.enableSwipeToDismiss((viewGroup, reverseSortedPositions) -> { - // Avoids conflicts with action mode - finishActionMode(); + ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { + @Override + public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { + return false; + } - for (int position : reverseSortedPositions) { - Note note; - try { - note = listAdapter.getItem(position); - } catch (IndexOutOfBoundsException e) { - Log.d(Constants.TAG, "Please stop swiping in the zone beneath the last card"); - continue; - } + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) { + // Avoids conflicts with action mode + finishActionMode(); + + Note note = listAdapter.getItem(viewHolder.getAdapterPosition()); getSelectedNotes().add(note); // Depending on settings and note status this action will... @@ -1144,37 +1203,44 @@ else if (Navigation.checkNavigation(Navigation.CATEGORY)) { } } } - }); - } else { - list.disableSwipeToDismiss(); + }; + + ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback); + itemTouchHelper.attachToRecyclerView(list); } - list.setAdapter(listAdapter); // Replace listview with Mr. Jingles if it is empty - if (notesLoadedEvent.notes.size() == 0) list.setEmptyView(empyListItem); + if (notesLoadedEvent.notes.size() == 0) { + emptyListItem.setVisibility(View.VISIBLE); + } else { + emptyListItem.setVisibility(View.GONE); + } // Restores listview position when turning back to list or when navigating reminders if (list != null && notesLoadedEvent.notes.size() > 0) { if (Navigation.checkNavigation(Navigation.REMINDERS)) { listViewPosition = listAdapter.getClosestNotePosition(); } + restoreListScrollPosition(); } - // Fade in the list view animate(progress_wheel).setDuration(getResources().getInteger(R.integer.list_view_fade_anim)).alpha(0); - animate(list).setDuration(getResources().getInteger(R.integer.list_view_fade_anim)).alpha(1); + // Fade in the list view + if (isNewList) { + animate(list).setDuration(getResources().getInteger(R.integer.list_view_fade_anim)).alpha(1); + } closeFab(); } private void restoreListScrollPosition() { - if (list.getCount() > listViewPosition) { - list.setSelectionFromTop(listViewPosition, listViewPositionOffset); + if (listAdapter.getInnerItemCount() > listViewPosition) { + list.getLayoutManager().scrollToPosition(listViewPosition); new Handler().postDelayed(fab::showFab, 150); } else { - list.setSelectionFromTop(0, 0); + list.getLayoutManager().scrollToPosition(0); } } @@ -1196,8 +1262,11 @@ public void trashNotes(boolean trash) { } // If list is empty again Mr Jingles will appear again - if (listAdapter.getCount() == 0) - list.setEmptyView(empyListItem); + if (listAdapter.isEmpty()) { + emptyListItem.setVisibility(View.VISIBLE); + } else { + emptyListItem.setVisibility(View.GONE); + } finishActionMode(); @@ -1251,7 +1320,7 @@ private void selectAllNotes() { } } selectedNotes.clear(); - for (int i = 0; i < listAdapter.getCount(); i++) { + for (int i = 0; i < listAdapter.getInnerItemCount(); i++) { selectedNotes.add(listAdapter.getItem(i)); listAdapter.addSelectedItem(i); } @@ -1287,12 +1356,14 @@ public void onPositive(MaterialDialog materialDialog) { private void deleteNotesExecute() { listAdapter.remove(getSelectedNotes()); new NoteProcessorDelete(getSelectedNotes()).process(); - list.clearChoices(); selectedNotes.clear(); finishActionMode(); // If list is empty again Mr Jingles will appear again - if (listAdapter.getCount() == 0) - list.setEmptyView(empyListItem); + if (listAdapter.isEmpty()) { + emptyListItem.setVisibility(View.VISIBLE); + } else { + emptyListItem.setVisibility(View.GONE); + } mainActivity.showMessage(R.string.note_deleted, ONStyle.ALERT); } @@ -1329,14 +1400,16 @@ public void archiveNotes(boolean archive) { listAdapter.replace(note, listAdapter.getPosition(note)); } } - - listAdapter.notifyDataSetChanged(); finishActionMode(); // If list is empty again Mr Jingles will appear again - if (listAdapter.getCount() == 0) list.setEmptyView(empyListItem); - + if (listAdapter.isEmpty()) { + emptyListItem.setVisibility(View.VISIBLE); + } else { + emptyListItem.setVisibility(View.GONE); + } // Advice to user + Crouton.clearCroutonsForActivity(mainActivity); int msg = archive ? R.string.note_archived : R.string.note_unarchived; Style style = archive ? ONStyle.WARN : ONStyle.INFO; mainActivity.showMessage(msg, style); @@ -1357,7 +1430,10 @@ public void archiveNotes(boolean archive) { */ private void trackModifiedNotes(List modifiedNotesToTrack) { for (Note note : modifiedNotesToTrack) { - undoNotesMap.put(listAdapter.getPosition(note), note); + int pos = listAdapter.getPosition(note); + if (pos >= 0) { + undoNotesMap.put(pos, note); + } } } @@ -1449,8 +1525,11 @@ private void categorizeNotesExecute(Category category) { finishActionMode(); // If list is empty again Mr Jingles will appear again - if (listAdapter.getCount() == 0) - list.setEmptyView(empyListItem); + if (listAdapter.isEmpty()) { + emptyListItem.setVisibility(View.VISIBLE); + } else { + emptyListItem.setVisibility(View.GONE); + } // Advice to user String msg; @@ -1514,15 +1593,12 @@ private void tagNotesExecute(List tags, Integer[] selectedTags, Integer[] p tagNote(tags, selectedTags, note); } - // Clears data structures - list.clearChoices(); - - // Refreshes list - list.invalidateViews(); - // If list is empty again Mr Jingles will appear again - if (listAdapter.getCount() == 0) - list.setEmptyView(empyListItem); + if (listAdapter.isEmpty()) { + emptyListItem.setVisibility(View.VISIBLE); + } else { + emptyListItem.setVisibility(View.GONE); + } if (getActionMode() != null) { getActionMode().finish(); @@ -1557,20 +1633,10 @@ private void tagNote(List tags, Integer[] selectedTags, Note note) { DbHelper.getInstance().updateNote(note, false); } - -// private void synchronizeSelectedNotes() { -// new DriveSyncTask(mainActivity).execute(new ArrayList(getSelectedNotes())); -// // Clears data structures -// listAdapter.clearSelectedItems(); -// list.clearChoices(); -// finishActionMode(); -// } - - @Override public void onUndo(Parcelable undoToken) { // Cycles removed items to re-insert into adapter - for (Integer notePosition : undoNotesMap.keySet()) { + for (Integer notePosition : undoNotesMap.descendingMap().keySet()) { Note currentNote = undoNotesMap.get(notePosition); // Manages uncategorize or archive undo if ((undoCategorize && !Navigation.checkNavigationCategory(undoCategoryMap.get(currentNote))) @@ -1583,7 +1649,7 @@ public void onUndo(Parcelable undoToken) { listAdapter.replace(currentNote, listAdapter.getPosition(currentNote)); // Manages trash undo } else { - list.insert(notePosition, currentNote); + listAdapter.add(notePosition, currentNote); } } @@ -1630,7 +1696,6 @@ else if (undoCategorize) undoNotesMap.clear(); undoCategoryMap.clear(); undoArchivedMap.clear(); - list.clearChoices(); ubc.hideUndoBar(false); fab.showFab(); diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/MainActivity.java b/omniNotes/src/main/java/it/feio/android/omninotes/MainActivity.java index aea0def694..0c70b0e2bc 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/MainActivity.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/MainActivity.java @@ -23,7 +23,7 @@ import android.content.pm.ActivityInfo; import android.net.Uri; import android.os.Bundle; -import android.support.design.widget.CoordinatorLayout; +import android.support.design.widget.AppBarLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; @@ -37,6 +37,10 @@ import android.widget.DatePicker; import android.widget.TimePicker; import android.widget.Toast; + +import java.util.ArrayList; +import java.util.HashMap; + import butterknife.Bind; import butterknife.ButterKnife; import de.greenrobot.event.EventBus; @@ -52,17 +56,15 @@ import it.feio.android.omninotes.models.Category; import it.feio.android.omninotes.models.Note; import it.feio.android.omninotes.utils.Constants; -import it.feio.android.omninotes.utils.MiscUtils; - -import java.util.ArrayList; -import java.util.HashMap; +import it.feio.android.omninotes.utils.SystemHelper; public class MainActivity extends BaseActivity implements OnDateSetListener, OnTimeSetListener { @Bind(R.id.crouton_handle) ViewGroup croutonViewContainer; - @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.drawer_layout) DrawerLayout drawerLayout; + @Bind(R.id.outer_toolbar) AppBarLayout outerToolbar; + Toolbar toolbar; public final String FRAGMENT_DRAWER_TAG = "fragment_drawer"; public final String FRAGMENT_LIST_TAG = "fragment_list"; @@ -77,7 +79,9 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setTheme(R.style.OmniNotesTheme_ApiSpec); setContentView(R.layout.activity_main); + ButterKnife.bind(this); + toolbar = (Toolbar) outerToolbar.findViewById(R.id.toolbar); // This method starts the bootstrap chain. checkPassword(); @@ -300,7 +304,7 @@ private void handleIntents() { if (i.getAction() == null) return; if (Constants.ACTION_RESTART_APP.equals(i.getAction())) { - MiscUtils.restartApp(getApplicationContext(), MainActivity.class); + SystemHelper.restartApp(getApplicationContext(), MainActivity.class); } if (receivedIntent(i)) { diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/SettingsActivity.java b/omniNotes/src/main/java/it/feio/android/omninotes/SettingsActivity.java index 439b1baa96..1ce8471528 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/SettingsActivity.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/SettingsActivity.java @@ -2,6 +2,7 @@ import android.app.Fragment; import android.os.Bundle; +import android.support.design.widget.AppBarLayout; import android.support.v7.app.ActionBarActivity; import android.support.v7.widget.Toolbar; import android.view.ViewGroup; @@ -16,8 +17,9 @@ public class SettingsActivity extends ActionBarActivity { - @Bind(R.id.toolbar) Toolbar toolbar; - @Bind(R.id.crouton_handle) ViewGroup croutonViewContainer; + @Bind(R.id.crouton_handle) ViewGroup croutonViewContainer; + @Bind(R.id.outer_toolbar) AppBarLayout outerToolbar; + Toolbar toolbar; private List backStack = new ArrayList<>(); @@ -26,7 +28,10 @@ public class SettingsActivity extends ActionBarActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_settings); + ButterKnife.bind(this); + toolbar = (Toolbar) outerToolbar.findViewById(R.id.toolbar); + initUI(); getFragmentManager().beginTransaction().replace(R.id.content_frame, new SettingsFragment()).commit(); } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/SettingsFragment.java b/omniNotes/src/main/java/it/feio/android/omninotes/SettingsFragment.java index e267db632f..07465d917c 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/SettingsFragment.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/SettingsFragment.java @@ -44,7 +44,6 @@ import it.feio.android.omninotes.helpers.AnalyticsHelper; import it.feio.android.omninotes.helpers.PermissionsHelper; import it.feio.android.omninotes.models.ONStyle; -import it.feio.android.omninotes.models.listeners.OnPermissionRequestedListener; import it.feio.android.omninotes.utils.*; import org.apache.commons.lang.StringUtils; @@ -107,6 +106,8 @@ public boolean onOptionsItemSelected(MenuItem item) { case android.R.id.home: getActivity().onBackPressed(); break; + default: + Log.e(Constants.TAG, "Wrong element choosen: " + item.getItemId()); } return super.onOptionsItemSelected(item); } @@ -290,7 +291,7 @@ public void onResume() { + languageName.substring(1, languageName.length())); lang.setOnPreferenceChangeListener((preference, value) -> { OmniNotes.updateLanguage(getActivity(), value.toString()); - MiscUtils.restartApp(getActivity().getApplicationContext(), MainActivity.class); + SystemHelper.restartApp(getActivity().getApplicationContext(), MainActivity.class); return false; }); } @@ -331,6 +332,41 @@ public void onResume() { } + // First day of week + final ListPreference firstDayOfWeek = (ListPreference) findPreference("settings_first_day_of_week"); + if (firstDayOfWeek != null) { + int firstDayOfWeekIndex = firstDayOfWeek.findIndexOfValue(prefs.getString("settings_first_day_of_week", + Constants.PREF_FIRST_DAY_OF_WEEK_DEFAULT)); + String firstDayOfWeekString = getResources().getStringArray(R.array.first_day_of_week)[firstDayOfWeekIndex]; + firstDayOfWeek.setSummary(firstDayOfWeekString); + firstDayOfWeek.setOnPreferenceChangeListener((preference, newValue) -> { + int firstDayOfWeekIndex1 = firstDayOfWeek.findIndexOfValue(newValue.toString()); + String firstDayOfWeekString1 = getResources().getStringArray(R.array.first_day_of_week)[firstDayOfWeekIndex1]; + firstDayOfWeek.setSummary(firstDayOfWeekString1); + prefs.edit().putString("settings_first_day_of_week", newValue.toString()).commit(); + firstDayOfWeek.setValueIndex(firstDayOfWeekIndex1); + return false; + }); + } + + + // Simple calendar + final SwitchPreference simpleCalendar = (SwitchPreference) findPreference("settings_simple_calendar"); + if (simpleCalendar != null) { + if (firstDayOfWeek != null) { + firstDayOfWeek.setEnabled(!simpleCalendar.isChecked()); + } + simpleCalendar.setOnPreferenceChangeListener((preference, newValue) -> { + boolean value = (Boolean) newValue; + simpleCalendar.setChecked(value); + if (firstDayOfWeek != null) { + firstDayOfWeek.setEnabled(!value); + } + return false; + }); + } + + // Checklists final ListPreference checklist = (ListPreference) findPreference("settings_checked_items_behavior"); if (checklist != null) { @@ -437,7 +473,7 @@ public void onPositive(MaterialDialog dialog) { StorageHelper.delete(getActivity(), attachmentsDir.getAbsolutePath()); File cacheDir = StorageHelper.getCacheDir(getActivity()); StorageHelper.delete(getActivity(), cacheDir.getAbsolutePath()); - MiscUtils.restartApp(getActivity().getApplicationContext(), MainActivity.class); + SystemHelper.restartApp(getActivity().getApplicationContext(), MainActivity.class); } }) .build().show(); @@ -461,7 +497,7 @@ public void onPositive(MaterialDialog materialDialog) { AnalyticsHelper.trackEvent(AnalyticsHelper.CATEGORIES.SETTING, "settings_tour_show_again"); prefs.edit().putBoolean(Constants.PREF_TOUR_COMPLETE, false).commit(); - MiscUtils.restartApp(getActivity().getApplicationContext(), MainActivity.class); + SystemHelper.restartApp(getActivity().getApplicationContext(), MainActivity.class); } }).build().show(); return false; @@ -681,6 +717,9 @@ public void onActivityResult(int requestCode, int resultCode, Intent intent) { String notificationSound = uri == null ? null : uri.toString(); prefs.edit().putString("settings_notification_ringtone", notificationSound).apply(); break; + + default: + Log.e(Constants.TAG, "Wrong element choosen: " + requestCode); } } } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/SketchFragment.java b/omniNotes/src/main/java/it/feio/android/omninotes/SketchFragment.java index 1cac09c75d..51fe603c43 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/SketchFragment.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/SketchFragment.java @@ -199,6 +199,8 @@ public boolean onOptionsItemSelected(MenuItem item) { case android.R.id.home: getActivity().onBackPressed(); break; + default: + Log.e(Constants.TAG, "Wrong element choosen: " + item.getItemId()); } return super.onOptionsItemSelected(item); } @@ -288,7 +290,7 @@ protected void setSeekbarProgress(int progress, int eraserOrStroke) { int calcProgress = progress > 1 ? progress : 1; int newSize = Math.round((size / 100f) * calcProgress); - int offset = Math.round((size - newSize) / 2); + int offset = (size - newSize) / 2; Log.v(Constants.TAG, "Stroke size " + newSize + " (" + calcProgress + "%)"); LayoutParams lp = new LayoutParams(newSize, newSize); diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/async/MainMenuTask.java b/omniNotes/src/main/java/it/feio/android/omninotes/async/MainMenuTask.java index a37297f23a..95e14cdbf2 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/async/MainMenuTask.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/async/MainMenuTask.java @@ -23,6 +23,7 @@ import android.content.res.TypedArray; import android.os.AsyncTask; import android.support.v4.app.Fragment; +import android.util.Log; import butterknife.Bind; import butterknife.ButterKnife; import de.greenrobot.event.EventBus; @@ -138,6 +139,8 @@ private boolean checkSkippableItem(int i) { if (dynamicMenu && dynamicNavigationLookupTable.getTrashed() == 0) skippable = true; break; + default: + Log.e(Constants.TAG, "Wrong element choosen: " + i); } return skippable; } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/async/ONDashClockExtension.java b/omniNotes/src/main/java/it/feio/android/omninotes/async/ONDashClockExtension.java deleted file mode 100644 index e8715f2523..0000000000 --- a/omniNotes/src/main/java/it/feio/android/omninotes/async/ONDashClockExtension.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2015 Federico Iosue (federico.iosue@gmail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package it.feio.android.omninotes.async; - -import android.annotation.SuppressLint; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.support.v4.content.LocalBroadcastManager; -import com.google.android.apps.dashclock.api.DashClockExtension; -import com.google.android.apps.dashclock.api.ExtensionData; -import it.feio.android.omninotes.MainActivity; -import it.feio.android.omninotes.R; -import it.feio.android.omninotes.db.DbHelper; -import it.feio.android.omninotes.models.Note; -import it.feio.android.omninotes.utils.Constants; -import it.feio.android.omninotes.utils.TextHelper; -import it.feio.android.omninotes.utils.date.DateUtils; - -import java.util.*; - - -public class ONDashClockExtension extends DashClockExtension { - - private enum Counters {ACTIVE, REMINDERS, TODAY, TOMORROW} - - - private DashClockUpdateReceiver mDashClockReceiver; - - - @Override - protected void onInitialize(boolean isReconnect) { - super.onInitialize(isReconnect); - LocalBroadcastManager broadcastMgr = LocalBroadcastManager.getInstance(this); - if (mDashClockReceiver != null) { - broadcastMgr.unregisterReceiver(mDashClockReceiver); - } - mDashClockReceiver = new DashClockUpdateReceiver(); - broadcastMgr.registerReceiver(mDashClockReceiver, new IntentFilter(Constants.INTENT_UPDATE_DASHCLOCK)); - } - - - @SuppressLint("DefaultLocale") - @Override - protected void onUpdateData(int reason) { - - Map> notesCounters = getNotesCounters(); - int reminders = notesCounters.get(Counters.REMINDERS).size(); - - StringBuilder expandedTitle = new StringBuilder(); - expandedTitle.append(notesCounters.get(Counters.ACTIVE).size()).append(" ").append(getString(R.string.notes).toLowerCase()); - if (reminders > 0) { - expandedTitle.append(", ").append(reminders).append(" ").append(getString(R.string.reminders)); - } - - StringBuilder expandedBody = new StringBuilder(); - - if (notesCounters.get(Counters.TODAY).size() > 0) { - expandedBody.append(notesCounters.get(Counters.TODAY).size()).append(" ").append(getString(R.string.today)).append(":"); - for (Note todayReminder : notesCounters.get(Counters.TODAY)) { - expandedBody.append(System.getProperty("line.separator")).append(("☆ ")).append(getNoteTitle(this, - todayReminder)); - } - expandedBody.append("\n"); - } - - if (notesCounters.get(Counters.TOMORROW).size() > 0) { - expandedBody.append(notesCounters.get(Counters.TOMORROW).size()).append(" ").append(getString(R.string.tomorrow)).append(":"); - for (Note tomorrowReminder : notesCounters.get(Counters.TOMORROW)) { - expandedBody.append(System.getProperty("line.separator")).append(("☆ ")).append(getNoteTitle(this, - tomorrowReminder)); - } - } - - // Publish the extension data update. - publishUpdate(new ExtensionData() - .visible(true) - .icon(R.drawable.ic_stat_literal_icon) - .status(String.valueOf(notesCounters.get(Counters.ACTIVE))) - .expandedTitle(expandedTitle.toString()) - .expandedBody(expandedBody.toString()) - .clickIntent(new Intent(this, MainActivity.class))); - } - - - private String getNoteTitle(Context context, Note note) { - return TextHelper.getAlternativeTitle(context, note, TextHelper.parseTitleAndContent(context, note)[0]); - } - - - private Map> getNotesCounters() { - Map noteCounters = new HashMap<>(); - List activeNotes = new ArrayList<>(); - List reminders = new ArrayList<>(); - List today = new ArrayList<>(); - List tomorrow = new ArrayList<>(); - for (Note note : DbHelper.getInstance().getNotesActive()) { - activeNotes.add(note); - if (note.getAlarm() != null && !note.isReminderFired()) { - reminders.add(note); - if (DateUtils.isSameDay(Long.valueOf(note.getAlarm()), Calendar.getInstance().getTimeInMillis())) { - today.add(note); - } else if ((Long.valueOf(note.getAlarm()) - Calendar.getInstance().getTimeInMillis()) / (1000 * 60 * - 60) < 24) { - tomorrow.add(note); - } - } - } - noteCounters.put(Counters.ACTIVE, activeNotes); - noteCounters.put(Counters.REMINDERS, reminders); - noteCounters.put(Counters.TODAY, today); - noteCounters.put(Counters.TOMORROW, tomorrow); - return noteCounters; - } - - - public class DashClockUpdateReceiver extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - onUpdateData(UPDATE_REASON_MANUAL); - } - - } -} diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/async/TextWorkerTask.java b/omniNotes/src/main/java/it/feio/android/omninotes/async/TextWorkerTask.java index ca4ade2c2a..0b1aca3c56 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/async/TextWorkerTask.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/async/TextWorkerTask.java @@ -18,8 +18,15 @@ package it.feio.android.omninotes.async; import android.app.Activity; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; import android.os.AsyncTask; +import android.text.Spannable; +import android.text.SpannableString; import android.text.Spanned; +import android.text.style.ForegroundColorSpan; +import android.text.style.LeadingMarginSpan; import android.view.View; import android.widget.TextView; import it.feio.android.omninotes.models.Note; @@ -58,8 +65,10 @@ protected void onPostExecute(Spanned[] titleAndContent) { if (isAlive()) { titleTextView.setText(titleAndContent[0]); if (titleAndContent[1].length() > 0) { - contentTextView.setText(titleAndContent[1]); - contentTextView.setVisibility(View.VISIBLE); + contentTextView.setText("✓ "); + contentTextView.measure(0, 0); + + contentTextView.setText(createIndentedText(SpannableString.valueOf(titleAndContent[1]), 0, contentTextView.getMeasuredWidth()));contentTextView.setVisibility(View.VISIBLE); } else { if (expandedView) { contentTextView.setVisibility(View.INVISIBLE); @@ -72,9 +81,8 @@ protected void onPostExecute(Spanned[] titleAndContent) { /** - * Cheks if activity is still alive and not finishing + * Checks if activity is still alive and not finishing * - * @param weakDetailFragmentReference * @return True or false */ private boolean isAlive() { @@ -83,4 +91,21 @@ private boolean isAlive() { } + static SpannableString createIndentedText(SpannableString text, int marginFirstLine, int marginNextLines) { + final int color = Color.rgb(128, 128, 128); + + text.setSpan(new LeadingMarginSpan.Standard(marginFirstLine, marginNextLines),0,text.length(),0); + + String t = text.toString(); + int index = 0; + while (index >= 0) { + ForegroundColorSpan fcs = new ForegroundColorSpan(color); + text.setSpan(fcs, index, index + 2, Spannable.SPAN_INCLUSIVE_INCLUSIVE); + index = t.indexOf('\n', index + 2); + } + + + return text; + } + } \ No newline at end of file diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/async/UpdaterTask.java b/omniNotes/src/main/java/it/feio/android/omninotes/async/UpdaterTask.java index bd043c6538..79217862ea 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/async/UpdaterTask.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/async/UpdaterTask.java @@ -32,6 +32,7 @@ import it.feio.android.omninotes.helpers.AnalyticsHelper; import it.feio.android.omninotes.utils.ConnectionManager; import it.feio.android.omninotes.utils.Constants; +import it.feio.android.omninotes.utils.SystemHelper; import java.io.BufferedReader; import java.io.IOException; @@ -45,7 +46,7 @@ public class UpdaterTask extends AsyncTask { - private final String BETA = " Beta "; + private static final String BETA = " Beta "; private final WeakReference mActivityReference; private final Activity mActivity; private final SharedPreferences prefs; @@ -136,7 +137,7 @@ private void showChangelog() { .build().show(); mActivity.getSharedPreferences(Constants.PREFS_NAME, Context.MODE_MULTI_PROCESS).edit().putString(Constants.PREF_CURRENT_APP_VERSION, - newVersion).commit(); + newVersion).apply(); } } catch (NameNotFoundException e) { Log.e(Constants.TAG, "Error retrieving app version", e); @@ -144,12 +145,6 @@ private void showChangelog() { } - /** - * Cheks if activity is still alive and not finishing - * - * @param weakActivityReference - * @return True or false - */ private boolean isAlive(WeakReference weakActivityReference) { return !(weakActivityReference.get() == null || weakActivityReference.get().isFinishing()); } @@ -158,21 +153,25 @@ private boolean isAlive(WeakReference weakActivityReference) { /** * Fetches application data from internet */ - public String getAppData() throws IOException { - StringBuilder sb = new StringBuilder(); - URLConnection conn = new URL(BuildConfig.VERSION_CHECK_URL).openConnection(); - InputStream is = conn.getInputStream(); - InputStreamReader inputStreamReader = new InputStreamReader(is); - BufferedReader br = new BufferedReader(inputStreamReader); - - String inputLine; - while ((inputLine = br.readLine()) != null) { - sb.append(inputLine); - } - inputStreamReader.close(); - is.close(); + private String getAppData() throws IOException { + InputStream is = null; + InputStreamReader inputStreamReader = null; + try { + StringBuilder sb = new StringBuilder(); + URLConnection conn = new URL(BuildConfig.VERSION_CHECK_URL).openConnection(); + is = conn.getInputStream(); + inputStreamReader = new InputStreamReader(is); + BufferedReader br = new BufferedReader(inputStreamReader); + + String inputLine; + while ((inputLine = br.readLine()) != null) { + sb.append(inputLine); + } - return sb.toString(); + return sb.toString(); + } finally { + SystemHelper.closeCloseable(inputStreamReader, is); + } } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/async/notes/SaveNoteTask.java b/omniNotes/src/main/java/it/feio/android/omninotes/async/notes/SaveNoteTask.java index 849b0d0ba9..5dd04db8c9 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/async/notes/SaveNoteTask.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/async/notes/SaveNoteTask.java @@ -90,7 +90,9 @@ private void purgeRemovedAttachments(Note note) { private Attachment getFixedAttachmentInstance(List deletedAttachments, Attachment attachment) { for (Attachment deletedAttachment : deletedAttachments) { - if (deletedAttachment.getId() == attachment.getId()) return deletedAttachment; + if (deletedAttachment.getId().equals(attachment.getId())) { + return deletedAttachment; + } } return attachment; } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/extensions/ONDashClockExtension.java b/omniNotes/src/main/java/it/feio/android/omninotes/extensions/ONDashClockExtension.java index 05c111208b..ea6064e34f 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/extensions/ONDashClockExtension.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/extensions/ONDashClockExtension.java @@ -3,7 +3,7 @@ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundatibehaon, either version 3 of the License, or + * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -61,28 +61,28 @@ protected void onInitialize(boolean isReconnect) { protected void onUpdateData(int reason) { Map> notesCounters = getNotesCounters(); - int reminders = notesCounters.get(Counters.REMINDERS).size(); + int reminders = notesCounters.get(Counters.REMINDERS.name()).size(); StringBuilder expandedTitle = new StringBuilder(); - expandedTitle.append(notesCounters.get(Counters.ACTIVE).size()).append(" ").append(getString(R.string.notes).toLowerCase()); + expandedTitle.append(notesCounters.get(Counters.ACTIVE.name()).size()).append(" ").append(getString(R.string.notes).toLowerCase()); if (reminders > 0) { expandedTitle.append(", ").append(reminders).append(" ").append(getString(R.string.reminders)); } StringBuilder expandedBody = new StringBuilder(); - if (notesCounters.get(Counters.TODAY).size() > 0) { - expandedBody.append(notesCounters.get(Counters.TODAY).size()).append(" ").append(getString(R.string.today)).append(":"); - for (Note todayReminder : notesCounters.get(Counters.TODAY)) { + if (notesCounters.get(Counters.TODAY.name()).size() > 0) { + expandedBody.append(notesCounters.get(Counters.TODAY.name()).size()).append(" ").append(getString(R.string.today)).append(":"); + for (Note todayReminder : notesCounters.get(Counters.TODAY.name())) { expandedBody.append(System.getProperty("line.separator")).append(("☆ ")).append(getNoteTitle(this, todayReminder)); } expandedBody.append("\n"); } - if (notesCounters.get(Counters.TOMORROW).size() > 0) { - expandedBody.append(notesCounters.get(Counters.TOMORROW).size()).append(" ").append(getString(R.string.tomorrow)).append(":"); - for (Note tomorrowReminder : notesCounters.get(Counters.TOMORROW)) { + if (notesCounters.get(Counters.TOMORROW.name()).size() > 0) { + expandedBody.append(notesCounters.get(Counters.TOMORROW.name()).size()).append(" ").append(getString(R.string.tomorrow)).append(":"); + for (Note tomorrowReminder : notesCounters.get(Counters.TOMORROW.name())) { expandedBody.append(System.getProperty("line.separator")).append(("☆ ")).append(getNoteTitle(this, tomorrowReminder)); } @@ -94,7 +94,7 @@ protected void onUpdateData(int reason) { publishUpdate(new ExtensionData() .visible(true) .icon(R.drawable.ic_stat_literal_icon) - .status(String.valueOf(notesCounters.get(Counters.ACTIVE).size())) + .status(String.valueOf(notesCounters.get(Counters.ACTIVE.name()).size())) .expandedTitle(expandedTitle.toString()) .expandedBody(expandedBody.toString()) .clickIntent(launchIntent)); diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/helpers/AttachmentsHelper.java b/omniNotes/src/main/java/it/feio/android/omninotes/helpers/AttachmentsHelper.java new file mode 100644 index 0000000000..47a79d733f --- /dev/null +++ b/omniNotes/src/main/java/it/feio/android/omninotes/helpers/AttachmentsHelper.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2016 Federico Iosue (federico.iosue@gmail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundatibehaon, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package it.feio.android.omninotes.helpers; + + +import it.feio.android.omninotes.models.Attachment; +import org.apache.commons.io.FileUtils; + +import java.io.File; + + +public class AttachmentsHelper { + + /** + * Retrieves attachment file size + * + * @param attachment Attachment to evaluate + * @return Human readable file size string + */ + public static String getSize(Attachment attachment) { + long sizeInKb = attachment.getSize(); + if (attachment.getSize() == 0) { + sizeInKb = new File(attachment.getUri().getPath()).length(); + } + return FileUtils.byteCountToDisplaySize(sizeInKb); + } +} diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/Attachment.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/Attachment.java index 98623504cd..4ef9d7b9af 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/models/Attachment.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/Attachment.java @@ -19,11 +19,12 @@ import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; +import it.feio.android.omninotes.commons.models.BaseAttachment; import java.util.Calendar; -public class Attachment extends it.feio.android.omninotes.commons.models.Attachment implements Parcelable { +public class Attachment extends BaseAttachment implements Parcelable { private Uri uri; @@ -39,7 +40,7 @@ public Attachment(long id, Uri uri, String name, long size, long length, String } - public Attachment(it.feio.android.omninotes.commons.models.Attachment attachment) { + public Attachment(BaseAttachment attachment) { super(attachment.getId(), attachment.getUriPath(), attachment.getName(), attachment.getSize(), attachment .getLength(), attachment.getMime_type()); this.uri = Uri.parse(attachment.getUriPath()); diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/Category.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/Category.java index c64bdc38f5..f7e6d75331 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/models/Category.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/Category.java @@ -18,9 +18,10 @@ import android.os.Parcel; import android.os.Parcelable; +import it.feio.android.omninotes.commons.models.BaseCategory; -public class Category extends it.feio.android.omninotes.commons.models.Category implements Parcelable { +public class Category extends BaseCategory implements Parcelable { private Category(Parcel in) { setId(in.readLong()); @@ -35,7 +36,7 @@ public Category() { } - public Category(it.feio.android.omninotes.commons.models.Category category) { + public Category(BaseCategory category) { super(category.getId(), category.getName(), category.getDescription(), category.getColor()); } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/Note.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/Note.java index cc31bb3ee8..6042f46944 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/models/Note.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/Note.java @@ -16,17 +16,16 @@ */ package it.feio.android.omninotes.models; -import android.content.Context; import android.os.Parcel; import android.os.Parcelable; -import it.feio.android.omninotes.helpers.date.DateHelper; -import it.feio.android.omninotes.utils.date.DateUtils; +import it.feio.android.omninotes.commons.models.BaseCategory; +import it.feio.android.omninotes.commons.models.BaseNote; import java.util.ArrayList; import java.util.List; -public class Note extends it.feio.android.omninotes.commons.models.Note implements Parcelable { +public class Note extends BaseNote implements Parcelable { // Not saved in DB private boolean passwordChecked = false; @@ -65,7 +64,7 @@ private Note(Parcel in) { setLatitude(in.readString()); setLongitude(in.readString()); setAddress(in.readString()); - setCategory(in.readParcelable(Category.class.getClassLoader())); + super.setCategory(in.readParcelable(Category.class.getClassLoader())); setLocked(in.readInt()); setChecklist(in.readInt()); in.readList(getAttachmentsList(), Attachment.class.getClassLoader()); @@ -137,7 +136,7 @@ public Category getCategory() { public void setCategory(Category category) { - if (category != null && category.getClass().equals(it.feio.android.omninotes.commons.models.Category.class)) { + if (category != null && category.getClass().equals(BaseCategory.class)) { setCategory(new Category(category)); } super.setCategory(category); diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/Tag.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/Tag.java index 5a8ea3f95c..6c88bf306c 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/models/Tag.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/Tag.java @@ -18,9 +18,10 @@ import android.os.Parcel; import android.os.Parcelable; +import it.feio.android.omninotes.commons.models.BaseTag; -public class Tag extends it.feio.android.omninotes.commons.models.Tag implements Parcelable { +public class Tag extends BaseTag implements Parcelable { private Tag(Parcel in) { setText(in.readString()); diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/adapters/NoteAdapter.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/adapters/NoteAdapter.java index ab560eca97..7d3222e964 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/models/adapters/NoteAdapter.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/adapters/NoteAdapter.java @@ -22,7 +22,11 @@ import android.net.Uri; import android.os.AsyncTask; import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.StaggeredGridLayoutManager; +import android.text.SpannableString; import android.text.Spanned; +import android.text.style.LeadingMarginSpan; import android.util.Log; import android.util.SparseBooleanArray; import android.view.LayoutInflater; @@ -33,60 +37,53 @@ import com.nhaarman.listviewanimations.util.Insertable; import it.feio.android.omninotes.R; import it.feio.android.omninotes.async.TextWorkerTask; +import it.feio.android.omninotes.helpers.NotesHelper; import it.feio.android.omninotes.models.Attachment; import it.feio.android.omninotes.models.Note; +import it.feio.android.omninotes.models.holders.EmptyHolder; import it.feio.android.omninotes.models.holders.NoteViewHolder; import it.feio.android.omninotes.utils.*; import java.util.ArrayList; import java.util.Calendar; import java.util.List; +import java.util.Vector; import java.util.concurrent.RejectedExecutionException; -public class NoteAdapter extends ArrayAdapter implements Insertable { +public class NoteAdapter extends RecyclerView.Adapter implements Insertable { private final Activity mActivity; private final int navigation; private List notes = new ArrayList<>(); private SparseBooleanArray selectedItems = new SparseBooleanArray(); private boolean expandedView; + private boolean gridView; private int layout; private LayoutInflater inflater; private long closestNoteReminder = Long.parseLong(Constants.TIMESTAMP_UNIX_EPOCH_FAR); private int closestNotePosition; + private static final int TYPE_HEADER_VIEW = Integer.MIN_VALUE; + private static final int TYPE_FOOTER_VIEW = Integer.MIN_VALUE + 1; + + private ArrayList mHeaderViews = new ArrayList<>(); + private ArrayList mFooterViews = new ArrayList<>(); + private int layoutID; public NoteAdapter(Activity activity, int layout, List notes) { - super(activity, R.layout.note_layout_expanded, notes); + super(); + this.mActivity = activity; - this.notes = notes; - this.layout = layout; - expandedView = layout == R.layout.note_layout_expanded; inflater = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); navigation = Navigation.getNavigation(); - manageCloserNote(notes, navigation); - } + this.notes = notes; + manageCloserNote(notes, navigation); + setLayout(layout); - @Override - public View getView(int position, View convertView, ViewGroup parent) { - Note note = notes.get(position); - NoteViewHolder holder; - if (convertView == null) { - convertView = inflater.inflate(layout, parent, false); - holder = buildHolder(convertView, parent); - convertView.setTag(holder); - } else { - holder = (NoteViewHolder) convertView.getTag(); - } - initText(note, holder); - initIcons(note, holder); - initDates(note, holder); - initThumbnail(note, holder); - manageSelectionColor(position, note, holder); - return convertView; + this.setHasStableIds(true); } @@ -105,7 +102,7 @@ private void manageSelectionColor(int position, Note note, NoteViewHolder holder private void initThumbnail(Note note, NoteViewHolder holder) { // Attachment thumbnail - if (expandedView) { + if (expandedView || gridView) { // If note is locked or without attachments nothing is shown if ((note.isLocked() && !mActivity.getSharedPreferences(Constants.PREFS_NAME, Context.MODE_MULTI_PROCESS).getBoolean("settings_password_access", false)) @@ -150,7 +147,7 @@ private void initIcons(Note note, NoteViewHolder holder) { // ...the locked with password state holder.lockedIcon.setVisibility(note.isLocked() ? View.VISIBLE : View.GONE); // ...the attachment icon for contracted view - if (!expandedView) { + if (!expandedView && !gridView) { holder.attachmentIcon.setVisibility(note.getAttachmentsList().size() > 0 ? View.VISIBLE : View.GONE); } } @@ -164,8 +161,6 @@ private void initText(Note note, NoteViewHolder holder) { } else { Spanned[] titleAndContent = TextHelper.parseTitleAndContent(mActivity, note); holder.title.setText(titleAndContent[0]); - holder.content.setText(titleAndContent[1]); - holder.title.setText(titleAndContent[0]); if (titleAndContent[1].length() > 0) { holder.content.setText(titleAndContent[1]); holder.content.setVisibility(View.VISIBLE); @@ -279,19 +274,20 @@ private void colorNote(Note note, View v, NoteViewHolder holder) { /** * Replaces notes */ - public void replace(Note note, int index) { + public void replace(@NonNull Note note, int index) { if (notes.indexOf(note) != -1) { - notes.remove(index); + remove(note); } else { index = notes.size(); } - notes.add(index, note); + add(index, note); } @Override - public void add(int i, @NonNull Object o) { - insert((Note) o, i); + public void add(int index, @NonNull Object o) { + notes.add(index, (Note) o); + notifyItemInserted(index); } @@ -301,6 +297,46 @@ public void remove(List notes) { } } + public void remove(@NonNull Note note) { + int pos = getPosition(note); + if (pos >= 0) { + notes.remove(note); + notifyItemRemoved(pos); + } + } + + public int getPosition(@NonNull Note note) { + return notes.indexOf(note); + } + + public Note getItem(int index) { + return notes.get(index); + } + + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public int getItemViewType(int position) { + int innerCount = getItemCount() - getHeaderViewsCount() - getFooterViewsCount(); + int headerViewsCountCount = getHeaderViewsCount(); + if (position < headerViewsCountCount) { + return TYPE_HEADER_VIEW + position; + } else if (headerViewsCountCount <= position && position < headerViewsCountCount + innerCount) { + + int innerItemViewType = layoutID; // to re-inflate views when layout changed (@see setLayout) + if(innerItemViewType >= Integer.MAX_VALUE / 2) { + throw new IllegalArgumentException("your adapter's return value of getViewTypeCount() must < Integer.MAX_VALUE / 2"); + } + return innerItemViewType + Integer.MAX_VALUE / 2; + } else { + return TYPE_FOOTER_VIEW + position - headerViewsCountCount - innerCount; + } + } + private NoteViewHolder buildHolder(View convertView, ViewGroup parent) { // Overrides font sizes with the one selected from user @@ -309,7 +345,140 @@ private NoteViewHolder buildHolder(View convertView, ViewGroup parent) { return new NoteViewHolder(convertView); } -} + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + int headerViewsCountCount = getHeaderViewsCount(); + if (viewType < TYPE_HEADER_VIEW + headerViewsCountCount) { + return new EmptyHolder(mHeaderViews.get(viewType - TYPE_HEADER_VIEW)); + } else if (viewType >= TYPE_FOOTER_VIEW && viewType < Integer.MAX_VALUE / 2) { + return new EmptyHolder(mFooterViews.get(viewType - TYPE_FOOTER_VIEW)); + } else { + NoteViewHolder holder; + View newview = inflater.inflate(layout, parent, false); + holder = buildHolder(newview, parent); + newview.setTag(holder); + return holder; + } + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + int headerViewsCountCount = getHeaderViewsCount(); + if (position >= headerViewsCountCount && position < headerViewsCountCount + (getItemCount() - getHeaderViewsCount() - getFooterViewsCount())) { + Note note = notes.get(position); + NoteViewHolder holderT = (NoteViewHolder) holder; + + initText(note, holderT); + initIcons(note, holderT); + initDates(note, holderT); + initThumbnail(note, holderT); + manageSelectionColor(position, note, holderT); + } else { + ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams(); + if(layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) { + ((StaggeredGridLayoutManager.LayoutParams) layoutParams).setFullSpan(true); + } + } + } + @Override + public int getItemCount() { + return notes.size() + getHeaderViewsCount() + getFooterViewsCount(); + } + + public int getInnerItemCount() { + return notes.size(); + } + + + public boolean isEmpty() { + return getItemCount() == 0; + } + + public void setNotes(ArrayList newNotes) { + int oldSize = getItemCount(); + + this.notes = newNotes; + manageCloserNote(notes, navigation); + + notifyItemRangeRemoved(0, oldSize); + notifyItemRangeChanged(0, getItemCount()); + } + + public void setLayout(int layout) { + this.layout = layout; + + expandedView = gridView = false; + switch (layout) { + case R.layout.note_layout_expanded: + expandedView = true; + layoutID = 1; + break; + case R.layout.note_layout_grid: + gridView = true; + layoutID = 2; + break; + default: + layoutID = 0; + break; + } + } + + /* Header / footer */ + public void addHeaderView(View header) { + + if (header == null) { + throw new RuntimeException("header is null"); + } + + mHeaderViews.add(header); + this.notifyDataSetChanged(); + } + + public void addFooterView(View footer) { + + if (footer == null) { + throw new RuntimeException("footer is null"); + } + + mFooterViews.add(footer); + this.notifyDataSetChanged(); + } + + public View getFooterView() { + return getFooterViewsCount()>0 ? mFooterViews.get(0) : null; + } + + public View getHeaderView() { + return getHeaderViewsCount()>0 ? mHeaderViews.get(0) : null; + } + + public void removeHeaderView(View view) { + mHeaderViews.remove(view); + this.notifyDataSetChanged(); + } + + public void removeFooterView(View view) { + mFooterViews.remove(view); + this.notifyDataSetChanged(); + } + + public int getHeaderViewsCount() { + return mHeaderViews.size(); + } + + public int getFooterViewsCount() { + return mFooterViews.size(); + } + + public boolean isHeader(int position) { + return getHeaderViewsCount() > 0 && position == 0; + } + + public boolean isFooter(int position) { + int lastPosition = getItemCount() - 1; + return getFooterViewsCount() > 0 && position == lastPosition; + } +} diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/holders/EmptyHolder.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/holders/EmptyHolder.java new file mode 100644 index 0000000000..fb4c0ed715 --- /dev/null +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/holders/EmptyHolder.java @@ -0,0 +1,12 @@ +package it.feio.android.omninotes.models.holders; + +import android.support.v7.widget.RecyclerView; +import android.view.View; + + +public class EmptyHolder extends RecyclerView.ViewHolder { + + public EmptyHolder(View itemView) { + super(itemView); + } +} diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/holders/NoteViewHolder.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/holders/NoteViewHolder.java index 1ce971f1f6..738f2982ff 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/models/holders/NoteViewHolder.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/holders/NoteViewHolder.java @@ -18,6 +18,7 @@ package it.feio.android.omninotes.models.holders; import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.ImageView; import butterknife.Bind; @@ -27,18 +28,19 @@ import it.feio.android.omninotes.models.views.SquareImageView; -public class NoteViewHolder { +public class NoteViewHolder extends RecyclerView.ViewHolder { public NoteViewHolder(View view) { + super(view); + ButterKnife.bind(this, view); } - @Bind(R.id.root) public View root; @Bind(R.id.card_layout) public View cardLayout; @Bind(R.id.category_marker) public View categoryMarker; @Bind(R.id.note_title) public TextView title; - @Bind(R.id.note_content) public TextView content; + @Bind(R.id.note_content) public android.widget.TextView content; @Bind(R.id.note_date) public TextView date; @Bind(R.id.archivedIcon) public ImageView archiveIcon; diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/listeners/AbsListViewScrollDetector.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/listeners/AbsListViewScrollDetector.java index 32878852de..268fea0c0a 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/models/listeners/AbsListViewScrollDetector.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/listeners/AbsListViewScrollDetector.java @@ -18,14 +18,13 @@ package it.feio.android.omninotes.models.listeners; import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.AbsListView; -public abstract class AbsListViewScrollDetector implements AbsListView.OnScrollListener { +public abstract class AbsListViewScrollDetector implements RecyclerView.OnScrollChangeListener { - private int mLastScrollY; - private int mPreviousFirstVisibleItem; private AbsListView mListView; private int mScrollThreshold; @@ -34,38 +33,18 @@ public abstract class AbsListViewScrollDetector implements AbsListView.OnScrollL public abstract void onScrollDown(); - - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - } - - @Override - public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { - if (isSameRow(firstVisibleItem)) { - int newScrollY = getTopItemScrollY(); - boolean isSignificantDelta = Math.abs(mLastScrollY - newScrollY) > mScrollThreshold; - if (isSignificantDelta) { - if (mLastScrollY > newScrollY) { - onScrollUp(); - } else { - onScrollDown(); - } - } - mLastScrollY = newScrollY; - } else { - if (firstVisibleItem > mPreviousFirstVisibleItem) { + public void onScrollChange(View view, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { + boolean isSignificantDelta = Math.abs(oldScrollY - scrollY) > mScrollThreshold; + if (isSignificantDelta) { + if (oldScrollY > scrollY) { onScrollUp(); } else { onScrollDown(); } - - mLastScrollY = getTopItemScrollY(); - mPreviousFirstVisibleItem = firstVisibleItem; } } - public void setScrollThreshold(int scrollThreshold) { mScrollThreshold = scrollThreshold; } @@ -76,10 +55,6 @@ public void setListView(@NonNull AbsListView listView) { } - private boolean isSameRow(int firstVisibleItem) { - return firstVisibleItem == mPreviousFirstVisibleItem; - } - private int getTopItemScrollY() { if (mListView == null || mListView.getChildAt(0) == null) { diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/listeners/OnFabItemClickedListener.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/listeners/OnFabItemClickedListener.java index 6101b424d1..2738e3b8b6 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/models/listeners/OnFabItemClickedListener.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/listeners/OnFabItemClickedListener.java @@ -19,5 +19,5 @@ public interface OnFabItemClickedListener { - void OnFabItemClick(int id); + void onFabItemClick(int id); } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/manager/ExStaggeredGridLayoutManager.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/manager/ExStaggeredGridLayoutManager.java new file mode 100644 index 0000000000..d3f3eee849 --- /dev/null +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/manager/ExStaggeredGridLayoutManager.java @@ -0,0 +1,56 @@ +package it.feio.android.omninotes.models.manager; + +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.StaggeredGridLayoutManager; +import android.view.View; + + +/** + * Created by cundong on 2015/10/23. + */ +public class ExStaggeredGridLayoutManager extends StaggeredGridLayoutManager { + + private final String TAG = getClass().getSimpleName(); + + GridLayoutManager.SpanSizeLookup mSpanSizeLookup; + + public ExStaggeredGridLayoutManager(int spanCount, int orientation) { + super(spanCount, orientation); + } + + /** + * Returns the current used by the GridLayoutManager. + * + * @return The current used by the GridLayoutManager. + */ + public GridLayoutManager.SpanSizeLookup getSpanSizeLookup() { + return mSpanSizeLookup; + } + + public void setSpanSizeLookup(GridLayoutManager.SpanSizeLookup spanSizeLookup) { + mSpanSizeLookup = spanSizeLookup; + } + + @Override + public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) { + //Log.d(TAG, "item count = " + getItemCount()); + for (int i = 0; i < getItemCount(); i++) { + + if (mSpanSizeLookup.getSpanSize(i) > 1) { + //Log.d(TAG, "lookup > 1 = " + i); + try { + View view = recycler.getViewForPosition(i); + if (view != null) { + StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams(); + lp.setFullSpan(true); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + } + super.onMeasure(recycler, state, widthSpec, heightSpec); + } +} \ No newline at end of file diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/misc/DynamicNavigationLookupTable.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/misc/DynamicNavigationLookupTable.java index 9b843e84d7..2d28f68248 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/models/misc/DynamicNavigationLookupTable.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/misc/DynamicNavigationLookupTable.java @@ -60,7 +60,9 @@ public void update() { if (notes.get(i).isTrashed()) trashed++; else if (notes.get(i).isArchived()) archived++; else if (notes.get(i).getAlarm() != null) reminders++; - if (notes.get(i).getCategory() == null || notes.get(i).getCategory().getId() == 0) uncategorized++; + if (notes.get(i).getCategory() == null || notes.get(i).getCategory().getId().equals(0L)) { + uncategorized++; + } } EventBus.getDefault().post(new DynamicNavigationReadyEvent()); Log.d(Constants.TAG, "Dynamic menu finished counting items"); diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/misc/HeaderSpanSizeLookup.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/misc/HeaderSpanSizeLookup.java new file mode 100644 index 0000000000..5a310512a4 --- /dev/null +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/misc/HeaderSpanSizeLookup.java @@ -0,0 +1,22 @@ +package it.feio.android.omninotes.models.misc; + +import android.support.v7.widget.GridLayoutManager; +import it.feio.android.omninotes.models.adapters.NoteAdapter; + + +public class HeaderSpanSizeLookup extends GridLayoutManager.SpanSizeLookup { + + private NoteAdapter adapter; + private int mSpanSize = 1; + + public HeaderSpanSizeLookup(NoteAdapter adapter, int spanSize) { + this.adapter = adapter; + this.mSpanSize = spanSize; + } + + @Override + public int getSpanSize(int position) { + boolean isHeaderOrFooter = adapter.isHeader(position) || adapter.isFooter(position); + return isHeaderOrFooter ? mSpanSize : 1; + } +} \ No newline at end of file diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/misc/ItemClickSupport.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/misc/ItemClickSupport.java new file mode 100644 index 0000000000..16657a5363 --- /dev/null +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/misc/ItemClickSupport.java @@ -0,0 +1,102 @@ +package it.feio.android.omninotes.models.misc; + +import android.support.v7.widget.RecyclerView; +import android.view.View; +import it.feio.android.omninotes.R; + +public class ItemClickSupport { + private final RecyclerView mRecyclerView; + private OnItemClickListener mOnItemClickListener; + private OnItemLongClickListener mOnItemLongClickListener; + private View.OnClickListener mOnClickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mOnItemClickListener != null) { + // ask the RecyclerView for the viewHolder of this view. + // then use it to get the position for the adapter + RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v); + mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v); + } + } + }; + private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + if (mOnItemLongClickListener != null) { + RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v); + return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v); + } + return false; + } + }; + private RecyclerView.OnChildAttachStateChangeListener mAttachListener + = new RecyclerView.OnChildAttachStateChangeListener() { + @Override + public void onChildViewAttachedToWindow(View view) { + // every time a new child view is attached add click listeners to it + if (mOnItemClickListener != null) { + view.setOnClickListener(mOnClickListener); + } + if (mOnItemLongClickListener != null) { + view.setOnLongClickListener(mOnLongClickListener); + } + } + + @Override + public void onChildViewDetachedFromWindow(View view) { + + } + }; + + private ItemClickSupport(RecyclerView recyclerView) { + mRecyclerView = recyclerView; + // the ID must be declared in XML, used to avoid + // replacing the ItemClickSupport without removing + // the old one from the RecyclerView + mRecyclerView.setTag(R.id.item_click_support, this); + mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener); + } + + public static ItemClickSupport addTo(RecyclerView view) { + // if there's already an ItemClickSupport attached + // to this RecyclerView do not replace it, use it + ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support); + if (support == null) { + support = new ItemClickSupport(view); + } + return support; + } + + public static ItemClickSupport removeFrom(RecyclerView view) { + ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support); + if (support != null) { + support.detach(view); + } + return support; + } + + public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) { + mOnItemClickListener = listener; + return this; + } + + public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) { + mOnItemLongClickListener = listener; + return this; + } + + private void detach(RecyclerView view) { + view.removeOnChildAttachStateChangeListener(mAttachListener); + view.setTag(R.id.item_click_support, null); + } + + public interface OnItemClickListener { + + void onItemClicked(RecyclerView recyclerView, int position, View v); + } + + public interface OnItemLongClickListener { + + boolean onItemLongClicked(RecyclerView recyclerView, int position, View v); + } +} \ No newline at end of file diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/views/ExRecyclerView.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/views/ExRecyclerView.java new file mode 100644 index 0000000000..5b6c43318f --- /dev/null +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/views/ExRecyclerView.java @@ -0,0 +1,89 @@ +package it.feio.android.omninotes.models.views; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.View; +import it.feio.android.omninotes.models.adapters.NoteAdapter; + + +public class ExRecyclerView extends RecyclerView { + public ExRecyclerView(Context context) { + super(context); + } + + public ExRecyclerView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public ExRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public void setHeaderView(View view) { + RecyclerView.Adapter outerAdapter = getAdapter(); + if (outerAdapter != null) { + NoteAdapter headerAndFooterAdapter = (NoteAdapter) outerAdapter; + if (headerAndFooterAdapter.getHeaderViewsCount() == 0) { + headerAndFooterAdapter.addHeaderView(view); + } + } + } + + public void setFooterView(View view) { + RecyclerView.Adapter outerAdapter = getAdapter(); + if (outerAdapter != null) { + NoteAdapter headerAndFooterAdapter = (NoteAdapter) outerAdapter; + if (headerAndFooterAdapter.getFooterViewsCount() == 0) { + headerAndFooterAdapter.addFooterView(view); + } + } + } + + public void removeFooterView() { + RecyclerView.Adapter outerAdapter = getAdapter(); + if (outerAdapter != null) { + int footerViewCounter = ((NoteAdapter) outerAdapter).getFooterViewsCount(); + if (footerViewCounter > 0) { + View footerView = ((NoteAdapter) outerAdapter).getFooterView(); + ((NoteAdapter) outerAdapter).removeFooterView(footerView); + } + } + } + + public void removeHeaderView() { + RecyclerView.Adapter outerAdapter = getAdapter(); + if (outerAdapter != null) { + int headerViewCounter = ((NoteAdapter) outerAdapter).getHeaderViewsCount(); + if (headerViewCounter > 0) { + View headerView = ((NoteAdapter) outerAdapter).getHeaderView(); + ((NoteAdapter) outerAdapter).removeFooterView(headerView); + } + } + } + + public int getLayoutPosition(RecyclerView.ViewHolder holder) { + RecyclerView.Adapter outerAdapter = getAdapter(); + if (outerAdapter != null) { + int headerViewCounter = ((NoteAdapter) outerAdapter).getHeaderViewsCount(); + if (headerViewCounter > 0) { + return holder.getLayoutPosition() - headerViewCounter; + } + } + + return holder.getLayoutPosition(); + } + + public int getAdapterPosition(RecyclerView.ViewHolder holder) { + RecyclerView.Adapter outerAdapter = getAdapter(); + if (outerAdapter != null) { + int headerViewCounter = ((NoteAdapter) outerAdapter).getHeaderViewsCount(); + if (headerViewCounter > 0) { + return holder.getAdapterPosition() - headerViewCounter; + } + } + + return holder.getAdapterPosition(); + } +} diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/views/Fab.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/views/Fab.java index a178b47d88..fab09b0b65 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/models/views/Fab.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/views/Fab.java @@ -2,6 +2,7 @@ import android.os.Build; import android.support.v4.view.ViewPropertyAnimatorListener; +import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateDecelerateInterpolator; @@ -19,7 +20,6 @@ import it.feio.android.omninotes.models.listeners.OnFabItemClickedListener; import it.feio.android.omninotes.utils.Constants; import it.feio.android.omninotes.utils.Display; -import it.feio.android.omninotes.utils.Navigation; import static android.support.v4.view.ViewCompat.animate; @@ -29,14 +29,14 @@ public class Fab { private boolean fabAllowed; private boolean fabHidden; private boolean fabExpanded; - private final ListView listView; + private final RecyclerView listView; private boolean expandOnLongClick; private View overlay; OnFabItemClickedListener onFabItemClickedListener; - public Fab(View fabView, ListView listView, boolean expandOnLongClick) { + public Fab(View fabView, RecyclerView listView, boolean expandOnLongClick) { this.fab = (FloatingActionsMenu) fabView; this.listView = listView; this.expandOnLongClick = expandOnLongClick; @@ -64,7 +64,7 @@ private void init() { } return true; }); - listView.setOnScrollListener( + listView.setOnScrollChangeListener( new AbsListViewScrollDetector() { public void onScrollUp() { if (fab != null) { @@ -104,7 +104,7 @@ public void onScrollDown() { private View.OnClickListener onClickListener = new View.OnClickListener() { @Override public void onClick(View v) { - onFabItemClickedListener.OnFabItemClick(v.getId()); + onFabItemClickedListener.onFabItemClick(v.getId()); } }; @@ -130,7 +130,7 @@ private void performAction(View v) { fab.toggle(); fabExpanded = false; } else { - onFabItemClickedListener.OnFabItemClick(v.getId()); + onFabItemClickedListener.onFabItemClick(v.getId()); } } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/views/NoteDecoration.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/views/NoteDecoration.java new file mode 100644 index 0000000000..61e5953daa --- /dev/null +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/views/NoteDecoration.java @@ -0,0 +1,21 @@ +package it.feio.android.omninotes.models.views; + +import android.graphics.Rect; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +public class NoteDecoration extends RecyclerView.ItemDecoration { + private int space; + + public NoteDecoration(int space) { + this.space = space; + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + outRect.left = space; + outRect.right = space; + outRect.bottom = space; + outRect.top = space; + } +} diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/models/views/SketchView.java b/omniNotes/src/main/java/it/feio/android/omninotes/models/views/SketchView.java index b7dbd683f5..8df9d6873a 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/models/views/SketchView.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/models/views/SketchView.java @@ -21,11 +21,13 @@ import android.content.Context; import android.graphics.*; import android.util.AttributeSet; +import android.util.Log; import android.util.Pair; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import it.feio.android.omninotes.models.listeners.OnDrawChangedListener; +import it.feio.android.omninotes.utils.Constants; import java.util.ArrayList; @@ -44,7 +46,6 @@ public class SketchView extends View implements OnTouchListener { private float eraserSize = DEFAULT_ERASER_SIZE; private int background = Color.WHITE; - // private Canvas mCanvas; private Path m_Path; private Paint m_Paint; private float mX, mY; @@ -81,7 +82,6 @@ public SketchView(Context context, AttributeSet attr) { m_Paint.setStrokeCap(Paint.Cap.ROUND); m_Paint.setStrokeWidth(strokeSize); m_Path = new Path(); - Paint newPaint = new Paint(m_Paint); invalidate(); } @@ -156,6 +156,8 @@ public boolean onTouch(View arg0, MotionEvent event) { touch_up(); invalidate(); break; + default: + Log.e(Constants.TAG, "Wrong element choosen: " + event.getAction()); } return true; } @@ -187,11 +189,9 @@ private void touch_start(float x, float y) { m_Paint.setStrokeWidth(strokeSize); } - Paint newPaint = new Paint(m_Paint); // Clones the mPaint object - // Avoids that a sketch with just erasures is saved if (!(paths.size() == 0 && mode == ERASER && bitmap == null)) { - paths.add(new Pair<>(m_Path, newPaint)); + paths.add(new Pair<>(m_Path, new Paint(m_Paint))); } m_Path.reset(); @@ -202,8 +202,6 @@ private void touch_start(float x, float y) { private void touch_move(float x, float y) { - float dx = Math.abs(x - mX); - float dy = Math.abs(y - mY); m_Path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2); mX = x; mY = y; @@ -212,13 +210,10 @@ private void touch_move(float x, float y) { private void touch_up() { m_Path.lineTo(mX, mY); - Paint newPaint = new Paint(m_Paint); // Clones the mPaint object - // Avoids that a sketch with just erasures is saved if (!(paths.size() == 0 && mode == ERASER && bitmap == null)) { - paths.add(new Pair<>(m_Path, newPaint)); + paths.add(new Pair<>(m_Path, new Paint(m_Paint))); } - // kill this so we don't double draw m_Path = new Path(); } @@ -302,6 +297,8 @@ public void setSize(int size, int eraserOrStroke) { case ERASER: eraserSize = size; break; + default: + Log.e(Constants.TAG, "Wrong element choosen: " + eraserOrStroke); } } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/utils/Constants.java b/omniNotes/src/main/java/it/feio/android/omninotes/utils/Constants.java index e1a61d27db..a1ef7dac74 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/utils/Constants.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/utils/Constants.java @@ -82,8 +82,8 @@ public interface Constants { String PREF_PASSWORD_ANSWER = "password_answer"; String PREF_KEEP_CHECKED = "keep_checked"; String PREF_KEEP_CHECKMARKS = "show_checkmarks"; - String PREF_EXPANDED_VIEW = "expanded_view"; String PREF_COLORS_APP_DEFAULT = "strip"; + String PREF_FIRST_DAY_OF_WEEK_DEFAULT = "locale_default"; String PREF_WIDGET_PREFIX = "widget_"; String PREF_SHOW_UNCATEGORIZED = "settings_show_uncategorized"; String PREF_AUTO_LOCATION = "settings_auto_location"; @@ -117,4 +117,10 @@ public interface Constants { int MENU_SORT_GROUP_ID = 11998811; String MERGED_NOTES_SEPARATOR = "----------------------"; + + // View modes + String PREF_VIEW_MODE = "pref_view_mode"; + int VIEW_MODE_CONTRACTED = 1; + int VIEW_MODE_EXPANDED = 2; + int VIEW_MODE_GRID = 3; } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/utils/FileHelper.java b/omniNotes/src/main/java/it/feio/android/omninotes/utils/FileHelper.java index 0e90681247..a49d44f06c 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/utils/FileHelper.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/utils/FileHelper.java @@ -33,6 +33,8 @@ import java.io.IOException; import java.io.InputStream; +import static java.lang.Long.parseLong; + public class FileHelper { @@ -68,11 +70,8 @@ public static String getPath(final Context context, final Uri uri) { } // DownloadsProvider else if (isDownloadsDocument(uri)) { - - final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), - Long.valueOf(id)); - + parseLong(DocumentsContract.getDocumentId(uri))); return getDataColumn(context, contentUri, null, null); } // MediaProvider diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/utils/GeocodeHelper.java b/omniNotes/src/main/java/it/feio/android/omninotes/utils/GeocodeHelper.java index 62f55f6114..d0ed090ef3 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/utils/GeocodeHelper.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/utils/GeocodeHelper.java @@ -124,7 +124,7 @@ public static void stop() { static String getAddressFromCoordinates(Context mContext, double latitude, - double longitude) throws IOException { + double longitude) throws IOException { String addressString = ""; Geocoder geocoder = new Geocoder(mContext, Locale.getDefault()); List
addresses = geocoder.getFromLocation(latitude, longitude, 1); @@ -177,52 +177,44 @@ public static void getCoordinatesFromAddress(String address, final OnGeoUtilResu public static List autocomplete(String input) { - String MAPS_API_KEY = BuildConfig.MAPS_API_KEY; - if (TextUtils.isEmpty(MAPS_API_KEY)) { - return Collections.emptyList(); + ArrayList resultList = new ArrayList<>(); + if (TextUtils.isEmpty(BuildConfig.MAPS_API_KEY)) { + return resultList; } - ArrayList resultList = null; - HttpURLConnection conn = null; StringBuilder jsonResults = new StringBuilder(); + InputStreamReader in = null; try { - URL url = new URL(PLACES_API_BASE + TYPE_AUTOCOMPLETE + OUT_JSON + "?key=" + MAPS_API_KEY + "&input=" + - URLEncoder.encode(input, "utf8")); + URL url = new URL(PLACES_API_BASE + TYPE_AUTOCOMPLETE + OUT_JSON + "?key=" + BuildConfig.MAPS_API_KEY + + "&input=" + URLEncoder.encode(input, "utf8")); conn = (HttpURLConnection) url.openConnection(); - InputStreamReader in = new InputStreamReader(conn.getInputStream()); - + in = new InputStreamReader(conn.getInputStream()); // Load the results into a StringBuilder int read; char[] buff = new char[1024]; while ((read = in.read(buff)) != -1) { jsonResults.append(buff, 0, read); } - } catch (MalformedURLException e) { - Log.e(Constants.TAG, "Error processing Places API URL"); - return null; - } catch (IOException e) { - Log.e(Constants.TAG, "Error connecting to Places API"); - return null; - } finally { - if (conn != null) { - conn.disconnect(); - } - } - - try { // Create a JSON object hierarchy from the results JSONObject jsonObj = new JSONObject(jsonResults.toString()); JSONArray predsJsonArray = jsonObj.getJSONArray("predictions"); - // Extract the Place descriptions from the results resultList = new ArrayList<>(predsJsonArray.length()); for (int i = 0; i < predsJsonArray.length(); i++) { resultList.add(predsJsonArray.getJSONObject(i).getString("description")); } + } catch (MalformedURLException e) { + Log.e(Constants.TAG, "Error processing Places API URL"); + } catch (IOException e) { + Log.e(Constants.TAG, "Error connecting to Places API"); } catch (JSONException e) { Log.e(Constants.TAG, "Cannot process JSON results", e); + } finally { + if (conn != null) { + conn.disconnect(); + } + SystemHelper.closeCloseable(in); } - return resultList; } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/utils/SpinnerDialog.java b/omniNotes/src/main/java/it/feio/android/omninotes/utils/SpinnerDialog.java deleted file mode 100644 index e0b16df4a6..0000000000 --- a/omniNotes/src/main/java/it/feio/android/omninotes/utils/SpinnerDialog.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2015 Federico Iosue (federico.iosue@gmail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package it.feio.android.omninotes.utils; - -import android.app.Dialog; -import android.app.ProgressDialog; -import android.os.Bundle; -import android.support.v4.app.DialogFragment; - - -public class SpinnerDialog extends DialogFragment { - - public SpinnerDialog() { - // use empty constructors. If something is needed use onCreate's - } - - - @Override - public Dialog onCreateDialog(final Bundle savedInstanceState) { - - ProgressDialog dialog = new ProgressDialog(getActivity()); -// this.setStyle(STYLE_NO_TITLE, getTheme()); // You can use styles or -// // inflate a view -// dialog.setMessage("Spinning.."); // set your messages if not inflated - // from XML -// dialog.setView(new Spinner(getActivity(), STYLE_NO_TITLE)); - dialog.setCancelable(false); - - return dialog; - } -} \ No newline at end of file diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/utils/StorageHelper.java b/omniNotes/src/main/java/it/feio/android/omninotes/utils/StorageHelper.java index 45b7617b69..6e2f9bad67 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/utils/StorageHelper.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/utils/StorageHelper.java @@ -226,7 +226,9 @@ public static String getRealPathFromURI(Context mContext, Uri contentUri) { } int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); - return cursor.getString(column_index); + String path = cursor.getString(column_index); + cursor.close(); + return path; } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/utils/MiscUtils.java b/omniNotes/src/main/java/it/feio/android/omninotes/utils/SystemHelper.java similarity index 60% rename from omniNotes/src/main/java/it/feio/android/omninotes/utils/MiscUtils.java rename to omniNotes/src/main/java/it/feio/android/omninotes/utils/SystemHelper.java index ab06310e58..6cf2835c82 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/utils/MiscUtils.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/utils/SystemHelper.java @@ -1,18 +1,16 @@ package it.feio.android.omninotes.utils; -import android.app.AlarmManager; -import android.app.PendingIntent; import android.content.Context; -import android.content.Intent; -import it.feio.android.omninotes.MainActivity; +import android.util.Log; -import java.util.Calendar; +import java.io.Closeable; +import java.io.IOException; /** - * Created by fede on 29/05/15. + * Various utility methods */ -public class MiscUtils { +public class SystemHelper { /** * Performs a full app restart @@ -28,4 +26,22 @@ public static void restartApp(final Context mContext, Class activityClass) { // mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent); System.exit(0); } + + + /** + * Performs closure of multiple closeables objects + * + * @param closeables Objects to close + */ + public static void closeCloseable(Closeable... closeables) { + for (Closeable closeable : closeables) { + if (closeable != null) { + try { + closeable.close(); + } catch (IOException e) { + Log.w(Constants.TAG, "Can't close " + closeable, e); + } + } + } + } } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/utils/TextHelper.java b/omniNotes/src/main/java/it/feio/android/omninotes/utils/TextHelper.java index 1eac4541b3..1f0ca19255 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/utils/TextHelper.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/utils/TextHelper.java @@ -76,13 +76,13 @@ public static Spanned[] parseTitleAndContent(Context mContext, Note note) { titleText = titleText.replace(it.feio.android.checklistview.interfaces.Constants.CHECKED_SYM, it.feio.android.checklistview.interfaces.Constants.CHECKED_ENTITY).replace( it.feio.android.checklistview.interfaces.Constants.UNCHECKED_SYM, - it.feio.android.checklistview.interfaces.Constants.UNCHECKED_ENTITY); + "⎕ "); titleSpanned = Html.fromHtml(titleText); contentText = contentText .replace(it.feio.android.checklistview.interfaces.Constants.CHECKED_SYM, it.feio.android.checklistview.interfaces.Constants.CHECKED_ENTITY) .replace(it.feio.android.checklistview.interfaces.Constants.UNCHECKED_SYM, - it.feio.android.checklistview.interfaces.Constants.UNCHECKED_ENTITY) + "⎕ ") .replace(System.getProperty("line.separator"), "
"); contentSpanned = Html.fromHtml(contentText); } else { diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/utils/date/ReminderPickers.java b/omniNotes/src/main/java/it/feio/android/omninotes/utils/date/ReminderPickers.java index 8e5eaf896e..fce7eb652a 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/utils/date/ReminderPickers.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/utils/date/ReminderPickers.java @@ -19,6 +19,7 @@ import android.app.DatePickerDialog.OnDateSetListener; import android.app.TimePickerDialog.OnTimeSetListener; +import android.content.SharedPreferences; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; @@ -30,6 +31,7 @@ import java.util.Calendar; import be.billington.calendar.recurrencepicker.RecurrencePickerDialog; +import it.feio.android.omninotes.MainActivity; import it.feio.android.omninotes.models.listeners.OnReminderPickedListener; import it.feio.android.omninotes.utils.Constants; @@ -107,6 +109,24 @@ protected void showDateTimeSelectors(long reminder) { DateUtils.is24HourMode(mActivity)); mRadialTimePickerDialog.show(mActivity.getSupportFragmentManager(), Constants.TAG); }, now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DAY_OF_MONTH)); + + SharedPreferences prefs = ((MainActivity) mActivity).prefs; + String firstDayOfWeekString = prefs.getString("settings_first_day_of_week", + Constants.PREF_FIRST_DAY_OF_WEEK_DEFAULT); + switch (firstDayOfWeekString) { + case "saturday": + mCalendarDatePickerDialog.setFirstDayOfWeek(Calendar.SATURDAY); + break; + + case "sunday": + mCalendarDatePickerDialog.setFirstDayOfWeek(Calendar.SUNDAY); + break; + + case "monday": + mCalendarDatePickerDialog.setFirstDayOfWeek(Calendar.MONDAY); + break; + } + mCalendarDatePickerDialog.show(mActivity.getSupportFragmentManager(), Constants.TAG); } diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/widget/WidgetConfigurationActivity.java b/omniNotes/src/main/java/it/feio/android/omninotes/widget/WidgetConfigurationActivity.java index ad4358bd77..2586c6cd6b 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/widget/WidgetConfigurationActivity.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/widget/WidgetConfigurationActivity.java @@ -21,6 +21,7 @@ import android.appwidget.AppWidgetManager; import android.content.Intent; import android.os.Bundle; +import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; @@ -32,6 +33,7 @@ import it.feio.android.omninotes.db.DbHelper; import it.feio.android.omninotes.models.Category; import it.feio.android.omninotes.models.adapters.NavDrawerCategoryAdapter; +import it.feio.android.omninotes.utils.Constants; import java.util.ArrayList; @@ -68,6 +70,9 @@ public void onCheckedChanged(RadioGroup group, int checkedId) { case R.id.widget_config_categories: categorySpinner.setEnabled(true); break; + + default: + Log.e(Constants.TAG, "Wrong element choosen: " + checkedId); } } }); diff --git a/omniNotes/src/main/java/it/feio/android/omninotes/widget/WidgetProvider.java b/omniNotes/src/main/java/it/feio/android/omninotes/widget/WidgetProvider.java index 10f521abc1..4b37504ab0 100644 --- a/omniNotes/src/main/java/it/feio/android/omninotes/widget/WidgetProvider.java +++ b/omniNotes/src/main/java/it/feio/android/omninotes/widget/WidgetProvider.java @@ -37,9 +37,9 @@ public abstract class WidgetProvider extends AppWidgetProvider { - public static String EXTRA_WORD = "it.feio.android.omninotes.widget.WORD"; - public static String TOAST_ACTION = "it.feio.android.omninotes.widget.NOTE"; - public static String EXTRA_ITEM = "it.feio.android.omninotes.widget.EXTRA_FIELD"; + public static final String EXTRA_WORD = "it.feio.android.omninotes.widget.WORD"; + public static final String TOAST_ACTION = "it.feio.android.omninotes.widget.NOTE"; + public static final String EXTRA_ITEM = "it.feio.android.omninotes.widget.EXTRA_FIELD"; @Override diff --git a/omniNotes/src/main/res/drawable-hdpi/ic_check.png b/omniNotes/src/main/res/drawable-hdpi/ic_check.png new file mode 100644 index 0000000000..748054eb7a Binary files /dev/null and b/omniNotes/src/main/res/drawable-hdpi/ic_check.png differ diff --git a/omniNotes/src/main/res/drawable-ldpi/ic_check.png b/omniNotes/src/main/res/drawable-ldpi/ic_check.png new file mode 100644 index 0000000000..2820014bad Binary files /dev/null and b/omniNotes/src/main/res/drawable-ldpi/ic_check.png differ diff --git a/omniNotes/src/main/res/drawable-mdpi/ic_check.png b/omniNotes/src/main/res/drawable-mdpi/ic_check.png new file mode 100644 index 0000000000..a52b42797a Binary files /dev/null and b/omniNotes/src/main/res/drawable-mdpi/ic_check.png differ diff --git a/omniNotes/src/main/res/drawable-xhdpi/ic_check.png b/omniNotes/src/main/res/drawable-xhdpi/ic_check.png new file mode 100644 index 0000000000..ab440fd096 Binary files /dev/null and b/omniNotes/src/main/res/drawable-xhdpi/ic_check.png differ diff --git a/omniNotes/src/main/res/drawable-xxhdpi/ic_check.png b/omniNotes/src/main/res/drawable-xxhdpi/ic_check.png new file mode 100644 index 0000000000..6b86e05460 Binary files /dev/null and b/omniNotes/src/main/res/drawable-xxhdpi/ic_check.png differ diff --git a/omniNotes/src/main/res/drawable-xxxhdpi/ic_check.png b/omniNotes/src/main/res/drawable-xxxhdpi/ic_check.png new file mode 100644 index 0000000000..27907500c1 Binary files /dev/null and b/omniNotes/src/main/res/drawable-xxxhdpi/ic_check.png differ diff --git a/omniNotes/src/main/res/layout/activity_main.xml b/omniNotes/src/main/res/layout/activity_main.xml index d16dd29a82..f6132f5b5a 100644 --- a/omniNotes/src/main/res/layout/activity_main.xml +++ b/omniNotes/src/main/res/layout/activity_main.xml @@ -18,10 +18,10 @@ - + android:fitsSystemWindows="true"> + + - + android:layout_below="@id/outer_toolbar" + android:background="@color/gray_bg" + app:layout_behavior="@string/appbar_scrolling_view_behavior"/> - + android:layout_below="@id/toolbar"/>--> - + + android:orientation="vertical" + tools:layout="@layout/toolbar" /> diff --git a/omniNotes/src/main/res/layout/activity_settings.xml b/omniNotes/src/main/res/layout/activity_settings.xml index df29a54089..0600a1db6b 100644 --- a/omniNotes/src/main/res/layout/activity_settings.xml +++ b/omniNotes/src/main/res/layout/activity_settings.xml @@ -6,7 +6,7 @@ android:clipToPadding="true" android:fitsSystemWindows="false"> - + . --> + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:pixlui="http://schemas.android.com/apk/com.neopixl.pixlui" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + + android:background="@color/gray_bg" + android:orientation="vertical"> - + android:layout_height="match_parent" + android:scrollbarSize="4dp" + android:scrollbarStyle="outsideOverlay" + app:layout_behavior="@string/appbar_scrolling_view_behavior" + android:scrollbarThumbVertical="@drawable/scroll_bar"> - + android:orientation="vertical"> - + android:layout="@layout/fragment_detail_attachments" /> - + - - - - - - - - - - - - - - - - - - - - - - - + android:layout="@layout/fragment_detail_attachments" /> - - - + + + + android:id="@+id/snackbar_placeholder" + android:layout_width="match_parent" + android:layout_height="200dp" + android:layout_alignParentBottom="true" + android:layout_marginBottom="@dimen/navigation_bar_height"> + + + + + + + + + + + + \ No newline at end of file diff --git a/omniNotes/src/main/res/layout/fragment_detail_attachments.xml b/omniNotes/src/main/res/layout/fragment_detail_attachments.xml index e210370e9d..e258abdd96 100644 --- a/omniNotes/src/main/res/layout/fragment_detail_attachments.xml +++ b/omniNotes/src/main/res/layout/fragment_detail_attachments.xml @@ -23,4 +23,7 @@ android:drawSelectorOnTop="true" android:listSelector="@drawable/icon_selector" android:numColumns="2" + android:padding="16dp" + android:horizontalSpacing="12dp" + android:verticalSpacing="12dp" android:stretchMode="columnWidth"/> \ No newline at end of file diff --git a/omniNotes/src/main/res/layout/fragment_detail_toolbar.xml b/omniNotes/src/main/res/layout/fragment_detail_toolbar.xml new file mode 100644 index 0000000000..5fd77db870 --- /dev/null +++ b/omniNotes/src/main/res/layout/fragment_detail_toolbar.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/omniNotes/src/main/res/layout/fragment_list.xml b/omniNotes/src/main/res/layout/fragment_list.xml index fb3160247b..7c374c0b3f 100644 --- a/omniNotes/src/main/res/layout/fragment_list.xml +++ b/omniNotes/src/main/res/layout/fragment_list.xml @@ -57,7 +57,7 @@ - . --> - @@ -130,4 +131,4 @@ android:contentDescription="@string/note_thumbnail" android:layout_gravity="center_vertical" /> - \ No newline at end of file + \ No newline at end of file diff --git a/omniNotes/src/main/res/layout/note_layout_grid.xml b/omniNotes/src/main/res/layout/note_layout_grid.xml new file mode 100644 index 0000000000..de14bb5029 --- /dev/null +++ b/omniNotes/src/main/res/layout/note_layout_grid.xml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/omniNotes/src/main/res/layout/toolbar.xml b/omniNotes/src/main/res/layout/toolbar.xml index 79cf40c73b..76d743b390 100644 --- a/omniNotes/src/main/res/layout/toolbar.xml +++ b/omniNotes/src/main/res/layout/toolbar.xml @@ -16,12 +16,41 @@ ~ along with this program. If not, see . --> - + android:layout_height="wrap_content" + android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" + android:fitsSystemWindows="true"> + + + + + + + + + + + diff --git a/omniNotes/src/main/res/menu/menu_list.xml b/omniNotes/src/main/res/menu/menu_list.xml index 7f4d4a03fc..ad012630df 100644 --- a/omniNotes/src/main/res/menu/menu_list.xml +++ b/omniNotes/src/main/res/menu/menu_list.xml @@ -150,6 +150,12 @@ app:showAsAction="never" android:title="@string/contracted_view" android:visible="false"/> + + + [b]New![/b] Gifs animation support within internal gallery + [i]Improved[/i] Added file size to attachments'action dialog + + [i]Improved[/i] Updated translations [u]Fix[/u] Location retrieval should work again thanks to new API key + [u]Fix[/u] Opening the same note twice from home widget broke the navigation [u]Fix[/u] Removed searched string label when changing sort order diff --git a/omniNotes/src/main/res/values-de-rDE/strings.xml b/omniNotes/src/main/res/values-de-rDE/strings.xml index e5af72dd6a..814e46cff6 100644 --- a/omniNotes/src/main/res/values-de-rDE/strings.xml +++ b/omniNotes/src/main/res/values-de-rDE/strings.xml @@ -147,7 +147,7 @@ Weiter Einfache Ansicht Erweiterte Ansicht - Grid view + Kachel Ansicht Verknüpfung hinzufügen Verknüpfung wurde dem Startbildschirm hinzugefügt Die Verknüpfung verweist auf eine gelöschte Notiz @@ -276,7 +276,6 @@ Minuten Einfacher Kalender und Uhrzeit Einfachen Kalender und Zeitauswahl für Erinnerungen benutzen - First day of week Anwendungstour Anwendungstour erneut zeigen Einstellungen mit einbeziehen (mit Passwort) @@ -316,9 +315,6 @@ Anhänge am unteren Rand Anhänge unterhalb der Notiz anzeigen Anhänge überhalb der Notiz anzeigen - Prettified dates - Dates are shown in a simplier format - Dates are shown in a more detailed format Datenschutz Fehlerberichte Sollte die App abstürzen, wird der Entwickler informiert um Ihnen zu helfen diff --git a/omniNotes/src/main/res/values/arrays.xml b/omniNotes/src/main/res/values/arrays.xml index ed5986eec4..e57fbf256a 100644 --- a/omniNotes/src/main/res/values/arrays.xml +++ b/omniNotes/src/main/res/values/arrays.xml @@ -230,4 +230,18 @@ edit + + Locale default + Sunday + Saturday + Monday + + + + locale_default + sunday + saturday + monday + + diff --git a/omniNotes/src/main/res/values/attrs.xml b/omniNotes/src/main/res/values/attrs.xml new file mode 100644 index 0000000000..fee0093a0d --- /dev/null +++ b/omniNotes/src/main/res/values/attrs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/omniNotes/src/main/res/values/colors.xml b/omniNotes/src/main/res/values/colors.xml index 9af64eac3a..3f7b9bd52b 100644 --- a/omniNotes/src/main/res/values/colors.xml +++ b/omniNotes/src/main/res/values/colors.xml @@ -57,6 +57,9 @@ #b9000000 #9b000000 + #fafafa + #f1f1f1 + #303F9F #ff9800 diff --git a/omniNotes/src/main/res/values/dimens.xml b/omniNotes/src/main/res/values/dimens.xml index c6542a986c..5aa6c9ddba 100644 --- a/omniNotes/src/main/res/values/dimens.xml +++ b/omniNotes/src/main/res/values/dimens.xml @@ -76,5 +76,6 @@ 32dp 24dp 64dp + 4dp \ No newline at end of file diff --git a/omniNotes/src/main/res/values/ids.xml b/omniNotes/src/main/res/values/ids.xml new file mode 100644 index 0000000000..824c6e7d07 --- /dev/null +++ b/omniNotes/src/main/res/values/ids.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/omniNotes/src/main/res/values/strings.xml b/omniNotes/src/main/res/values/strings.xml index aab1e51fdf..ad1e60008b 100644 --- a/omniNotes/src/main/res/values/strings.xml +++ b/omniNotes/src/main/res/values/strings.xml @@ -279,8 +279,8 @@ Preferences Beta About - Google+ - Subscribe to the beta program to keep up to date with the latest features + Join the beta program + Subscribe to the beta program via Google+ to access the latest features and to help develop Omni Notes Donate Support the development of this app with a non-profit donation Language diff --git a/omniNotes/src/main/res/values/styles.xml b/omniNotes/src/main/res/values/styles.xml index e964e53b9f..583f053fa1 100644 --- a/omniNotes/src/main/res/values/styles.xml +++ b/omniNotes/src/main/res/values/styles.xml @@ -107,6 +107,10 @@ @null + + diff --git a/omniNotes/src/main/res/xml/settings_interface.xml b/omniNotes/src/main/res/xml/settings_interface.xml index 12d0f6aa30..9ead2a1bbc 100644 --- a/omniNotes/src/main/res/xml/settings_interface.xml +++ b/omniNotes/src/main/res/xml/settings_interface.xml @@ -51,6 +51,13 @@ android:summary="@string/settings_simple_calendar_summary" android:title="@string/settings_simple_calendar"/> + +