Merge remote-tracking branch 'origin/master' into refresh-preview

# Conflicts:
#	app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NotePreviewFragment.java
#	app/src/main/res/layout/activity_single_note.xml
This commit is contained in:
stefan-niedermann 2019-12-30 20:46:28 +01:00
commit 15edaa3797
152 changed files with 2621 additions and 3828 deletions

3
.gitmodules vendored
View file

@ -1,3 +0,0 @@
[submodule "cert4android"]
path = cert4android
url = https://gitlab.com/bitfireAT/cert4android.git

View file

@ -2,12 +2,16 @@
An android client for [Nextcloud Notes App](https://github.com/nextcloud/notes/). An android client for [Nextcloud Notes App](https://github.com/nextcloud/notes/).
[![Build Status](https://travis-ci.org/stefan-niedermann/nextcloud-notes.svg?branch=master)](https://travis-ci.org/stefan-niedermann/nextcloud-notes) [![Build Status](https://travis-ci.org/stefan-niedermann/nextcloud-notes.svg?branch=master)](https://travis-ci.org/stefan-niedermann/nextcloud-notes)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/9f784826834042e8b512d531cab84711)](https://www.codacy.com/manual/info_147/nextcloud-notes?utm_source=github.com&utm_medium=referral&utm_content=stefan-niedermann/nextcloud-notes&utm_campaign=Badge_Grade)
[![GitHub issues](https://img.shields.io/github/issues/stefan-niedermann/nextcloud-notes.svg)](https://github.com/stefan-niedermann/nextcloud-notes/issues) [![GitHub issues](https://img.shields.io/github/issues/stefan-niedermann/nextcloud-notes.svg)](https://github.com/stefan-niedermann/nextcloud-notes/issues)
[![GitHub stars](https://img.shields.io/github/stars/stefan-niedermann/nextcloud-notes.svg)](https://github.com/stefan-niedermann/nextcloud-notes/stargazers) [![GitHub stars](https://img.shields.io/github/stars/stefan-niedermann/nextcloud-notes.svg)](https://github.com/stefan-niedermann/nextcloud-notes/stargazers)
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
## :arrow_forward: Access ## :arrow_forward: Access
[![Latest Release](https://img.shields.io/github/v/tag/stefan-niedermann/nextcloud-notes?label=latest+release&sort=semver)](https://github.com/stefan-niedermann/nextcloud-notes/releases)
[![F-Droid Release](https://img.shields.io/f-droid/v/it.niedermann.owncloud.notes)](https://f-droid.org/de/packages/it.niedermann.owncloud.notes/)
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png" [<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png"
alt="Get it on Play Store" alt="Get it on Play Store"
height="80">](https://play.google.com/store/apps/details?id=it.niedermann.owncloud.notes) height="80">](https://play.google.com/store/apps/details?id=it.niedermann.owncloud.notes)
@ -26,6 +30,7 @@ An android client for [Nextcloud Notes App](https://github.com/nextcloud/notes/)
| ![Screenshot of categories in sidebar](/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png) | ![Screenshot of list view](/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png) | ![Screenshot of edit view](/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png) | | ![Screenshot of categories in sidebar](/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png) | ![Screenshot of list view](/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png) | ![Screenshot of edit view](/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png) |
## :rocket: Features ## :rocket: Features
* Multiple accounts
* List, create, edit, share, search and delete notes * List, create, edit, share, search and delete notes
* Share text and links as new note into the app * Share text and links as new note into the app
* Mark notes as favorite * Mark notes as favorite
@ -50,10 +55,8 @@ An android client for [Nextcloud Notes App](https://github.com/nextcloud/notes/)
## :link: Requirements ## :link: Requirements
* [Nextcloud](https://nextcloud.com/) instance running * [Nextcloud](https://nextcloud.com/) instance running
* [Nextcloud Files](https://github.com/nextcloud/android) app enabled (> 3.9.0)
* [Nextcloud Notes](https://github.com/nextcloud/notes) app enabled * [Nextcloud Notes](https://github.com/nextcloud/notes) app enabled
## :notebook: License ## :notebook: License
This project is licensed under the [GNU GENERAL PUBLIC LICENSE](/LICENSE). This project is licensed under the [GNU GENERAL PUBLIC LICENSE](/LICENSE).
## :twisted_rightwards_arrows: Alternatives
If you dislike this app and you are looking for alternatives: Have a look at [MyOwnNotes](https://github.com/aykit/MyOwnNotes).

20
SSO Announcment.md Normal file
View file

@ -0,0 +1,20 @@
# SSO Announcment
Beginning with version `v2.0.0`, Notes for android will depend on Nextcloud Single-Sign-On.
## What do you need to do?
It is recommended, to perform a full synchronisation with the old version of the Notes app, before you upgrade.
You have likely installed an up-to-date version of the [Files app](https://play.google.com/store/apps/details?id=com.nextcloud.client). In this case, you will have nothing more to do.
In case you do not have it installed yet, you can get it for free from Play Store or F-Droid.
When you upgrade the Notes app, you will be asked to select an account (which you previously configured at the files app).
It is important that you **select** at the first run **the same account which you already were using** in the Notes app. This will make the first run smooth and make sure, that local edited, but not synced notes won't get lost.
## Benefits for you
- **:lock: Security benefits:** The notes app does no longer have to store a password itself.
- **:electric_plug: Reliability:** The complete network stack could be removed because all network activities are lead through the files app. This allows us to use e. g. the same stack for self signed certificates.
- **:bulb: Comfort:** You won't have to enter a server address, nor a username or a password. Just pick an existing account from the list.

View file

@ -13,8 +13,9 @@ android {
applicationId "it.niedermann.owncloud.notes" applicationId "it.niedermann.owncloud.notes"
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 28 targetSdkVersion 28
versionCode 47 versionCode 60
versionName "0.27.1" versionName "2.2.2"
// vectorDrawables.useSupportLibrary = true
} }
buildTypes { buildTypes {
release { release {
@ -26,21 +27,27 @@ android {
disable 'MissingTranslation' disable 'MissingTranslation'
abortOnError false abortOnError false
} }
dataBinding {
enabled = true
}
} }
dependencies { dependencies {
implementation project(':cert4android') implementation "com.github.nextcloud:Android-SingleSignOn:0.5.0-rc1"
implementation 'io.reactivex:rxandroid:1.2.1' implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'io.reactivex:rxjava:1.3.8' implementation 'io.reactivex:rxjava:1.3.8'
implementation 'com.yydcdut:markdown-processor:0.1.3' implementation 'com.yydcdut:markdown-processor:0.1.3'
implementation 'com.yydcdut:rxmarkdown-wrapper:0.1.3' implementation 'com.yydcdut:rxmarkdown-wrapper:0.1.3'
implementation 'com.jakewharton:butterknife:10.2.0' implementation 'com.github.bumptech.glide:glide:4.10.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'
implementation 'com.jakewharton:butterknife:10.2.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.1'
implementation "androidx.appcompat:appcompat:1.1.0" implementation "androidx.appcompat:appcompat:1.1.0"
implementation "androidx.recyclerview:recyclerview:1.0.0" implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation "com.google.android.material:material:1.0.0" implementation "com.google.android.material:material:1.0.0"
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])

View file

@ -1,37 +0,0 @@
package it.niedermann.owncloud.notes.util;
import junit.framework.TestCase;
/**
* Tests the NotesClientUtil
* Created by stefan on 24.09.15.
*/
public class NotesClientUtilTest extends TestCase {
public void testFormatURL() {
assertEquals("https://example.com/", NotesClientUtil.formatURL("example.com/"));
assertEquals("http://example.com/", NotesClientUtil.formatURL("http://example.com/"));
assertEquals("https://example.com/", NotesClientUtil.formatURL("example.com/index.php"));
assertEquals("https://example.com/", NotesClientUtil.formatURL("example.com/index.php/"));
assertEquals("https://example.com/", NotesClientUtil.formatURL("example.com/index.php/apps"));
assertEquals("https://example.com/", NotesClientUtil.formatURL("example.com/index.php/apps/notes"));
assertEquals("https://example.com/", NotesClientUtil.formatURL("example.com/index.php/apps/notes/api"));
assertEquals("https://example.com/", NotesClientUtil.formatURL("example.com/index.php/apps/notes/api/v0.2"));
assertEquals("https://example.com/", NotesClientUtil.formatURL("example.com/index.php/apps/notes/api/v0.2/notes"));
assertEquals("https://example.com/nextcloud/", NotesClientUtil.formatURL("example.com/nextcloud"));
assertEquals("http://example.com:443/nextcloud/", NotesClientUtil.formatURL("http://example.com:443/nextcloud/index.php/apps/notes/api/v0.2/notes"));
}
public void testIsHttp() {
assertTrue(NotesClientUtil.isHttp("http://example.com"));
assertTrue(NotesClientUtil.isHttp("http://www.example.com/"));
assertFalse(NotesClientUtil.isHttp("https://www.example.com/"));
assertFalse(NotesClientUtil.isHttp(null));
}
public void testIsValidURLTest() {
assertTrue(NotesClientUtil.isValidURL(null, "https://demo.owncloud.org/"));
assertFalse(NotesClientUtil.isValidURL(null, "https://www.example.com/"));
assertFalse(NotesClientUtil.isValidURL(null, "htp://www.example.com/"));
assertFalse(NotesClientUtil.isValidURL(null, null));
}
}

View file

@ -45,12 +45,6 @@
android:value="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity" /> android:value="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity" />
</activity> </activity>
<activity
android:name="it.niedermann.owncloud.notes.android.activity.SettingsActivity"
android:label="@string/settings_server_settings"
android:parentActivityName="it.niedermann.owncloud.notes.android.activity.PreferencesActivity"
android:windowSoftInputMode="stateVisible" />
<activity <activity
android:name="it.niedermann.owncloud.notes.android.activity.PreferencesActivity" android:name="it.niedermann.owncloud.notes.android.activity.PreferencesActivity"
android:label="@string/action_settings" android:label="@string/action_settings"

View file

@ -1,16 +1,19 @@
package it.niedermann.owncloud.notes.android; package it.niedermann.owncloud.notes.android;
import android.content.Context; import android.content.Context;
import androidx.appcompat.widget.AppCompatAutoCompleteTextView;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
import android.view.WindowManager; import android.view.WindowManager;
import androidx.appcompat.widget.AppCompatAutoCompleteTextView;
/** /**
* Extension of the {@link AppCompatAutoCompleteTextView}, but this one is always open, i.e. you can see the list of suggestions even the TextView is empty. * Extension of the {@link AppCompatAutoCompleteTextView}, but this one is always open, i.e. you can see the list of suggestions even the TextView is empty.
*/ */
public class AlwaysAutoCompleteTextView extends AppCompatAutoCompleteTextView { public class AlwaysAutoCompleteTextView extends AppCompatAutoCompleteTextView {
private static final String TAG = AlwaysAutoCompleteTextView.class.getSimpleName();
private int myThreshold; private int myThreshold;
public AlwaysAutoCompleteTextView(Context context) { public AlwaysAutoCompleteTextView(Context context) {
@ -50,7 +53,7 @@ public class AlwaysAutoCompleteTextView extends AppCompatAutoCompleteTextView {
} catch (WindowManager.BadTokenException e) { } catch (WindowManager.BadTokenException e) {
// https://github.com/stefan-niedermann/nextcloud-notes/issues/366 // https://github.com/stefan-niedermann/nextcloud-notes/issues/366
e.printStackTrace(); e.printStackTrace();
Log.e(AlwaysAutoCompleteTextView.class.getSimpleName(), "Exception", e); Log.e(TAG, "Exception", e);
} }
} }
} }

View file

@ -2,6 +2,7 @@ package it.niedermann.owncloud.notes.android.activity;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
@ -37,26 +38,23 @@ public class AboutActivity extends AppCompatActivity {
} }
private class TabsPagerAdapter extends FragmentPagerAdapter { private class TabsPagerAdapter extends FragmentPagerAdapter {
private final int PAGE_COUNT = 3;
public TabsPagerAdapter(FragmentManager fragmentManager) { TabsPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager); super(fragmentManager);
} }
@Override @Override
public int getCount() { public int getCount() {
return PAGE_COUNT; return 3;
} }
/** /**
* return the right fragment for the given position * return the right fragment for the given position
*/ */
@NonNull
@Override @Override
public Fragment getItem(int position) { public Fragment getItem(int position) {
switch (position) { switch (position) {
case 0:
return new AboutFragmentCreditsTab();
case 1: case 1:
return new AboutFragmentContributingTab(); return new AboutFragmentContributingTab();
@ -64,7 +62,7 @@ public class AboutActivity extends AppCompatActivity {
return new AboutFragmentLicenseTab(); return new AboutFragmentLicenseTab();
default: default:
return null; return new AboutFragmentCreditsTab();
} }
} }
@ -88,4 +86,10 @@ public class AboutActivity extends AppCompatActivity {
} }
} }
} }
@Override
public boolean onSupportNavigateUp() {
finish(); // close this activity as oppose to navigating up
return true;
}
} }

View file

@ -13,6 +13,7 @@ import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import java.util.Calendar; import java.util.Calendar;
import java.util.Objects;
import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.fragment.BaseNoteFragment; import it.niedermann.owncloud.notes.android.fragment.BaseNoteFragment;
@ -26,10 +27,13 @@ import it.niedermann.owncloud.notes.util.NoteUtil;
public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragment.NoteFragmentListener { public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragment.NoteFragmentListener {
private static final String TAG = EditNoteActivity.class.getSimpleName();
public static final String ACTION_SHORTCUT = "it.niedermann.owncloud.notes.shortcut"; public static final String ACTION_SHORTCUT = "it.niedermann.owncloud.notes.shortcut";
private static final String INTENT_GOOGLE_ASSISTANT = "com.google.android.gm.action.AUTO_SEND"; private static final String INTENT_GOOGLE_ASSISTANT = "com.google.android.gm.action.AUTO_SEND";
private static final String MIMETYPE_TEXT_PLAIN = "text/plain"; private static final String MIMETYPE_TEXT_PLAIN = "text/plain";
public static final String PARAM_NOTE_ID = "noteId"; public static final String PARAM_NOTE_ID = "noteId";
public static final String PARAM_ACCOUNT_ID = "accountId";
public static final String PARAM_CATEGORY = "category"; public static final String PARAM_CATEGORY = "category";
private BaseNoteFragment fragment; private BaseNoteFragment fragment;
@ -53,7 +57,7 @@ public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragm
@Override @Override
protected void onNewIntent(Intent intent) { protected void onNewIntent(Intent intent) {
super.onNewIntent(intent); super.onNewIntent(intent);
Log.d(getClass().getSimpleName(), "onNewIntent: " + intent.getLongExtra(PARAM_NOTE_ID, 0)); Log.d(TAG, "onNewIntent: " + intent.getLongExtra(PARAM_NOTE_ID, 0));
setIntent(intent); setIntent(intent);
if (fragment != null) { if (fragment != null) {
getFragmentManager().beginTransaction().detach(fragment).commit(); getFragmentManager().beginTransaction().detach(fragment).commit();
@ -66,6 +70,10 @@ public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragm
return getIntent().getLongExtra(PARAM_NOTE_ID, 0); return getIntent().getLongExtra(PARAM_NOTE_ID, 0);
} }
private long getAccountId() {
return getIntent().getLongExtra(PARAM_ACCOUNT_ID, 0);
}
/** /**
* Starts the note fragment for an existing note or a new note. * Starts the note fragment for an existing note or a new note.
* The actual behavior is triggered by the activity's intent. * The actual behavior is triggered by the activity's intent.
@ -73,7 +81,7 @@ public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragm
private void launchNoteFragment() { private void launchNoteFragment() {
long noteId = getNoteId(); long noteId = getNoteId();
if (noteId > 0) { if (noteId > 0) {
launchExistingNote(noteId); launchExistingNote(getAccountId(), noteId);
} else { } else {
launchNewNote(); launchNewNote();
} }
@ -85,7 +93,7 @@ public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragm
* *
* @param noteId ID of the existing note. * @param noteId ID of the existing note.
*/ */
private void launchExistingNote(long noteId) { private void launchExistingNote(long accountId, long noteId) {
final String prefKeyNoteMode = getString(R.string.pref_key_note_mode); final String prefKeyNoteMode = getString(R.string.pref_key_note_mode);
final String prefKeyLastMode = getString(R.string.pref_key_last_note_mode); final String prefKeyLastMode = getString(R.string.pref_key_last_note_mode);
final String prefValueEdit = getString(R.string.pref_value_mode_edit); final String prefValueEdit = getString(R.string.pref_value_mode_edit);
@ -99,7 +107,7 @@ public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragm
if (prefValuePreview.equals(mode) || (prefValueLast.equals(mode) && prefValuePreview.equals(lastMode))) { if (prefValuePreview.equals(mode) || (prefValueLast.equals(mode) && prefValuePreview.equals(lastMode))) {
editMode = false; editMode = false;
} }
launchExistingNote(noteId, editMode); launchExistingNote(accountId, noteId, editMode);
} }
/** /**
@ -110,16 +118,16 @@ public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragm
* <code>true</code> for {@link NoteEditFragment}, * <code>true</code> for {@link NoteEditFragment},
* <code>false</code> for {@link NotePreviewFragment}. * <code>false</code> for {@link NotePreviewFragment}.
*/ */
private void launchExistingNote(long noteId, boolean edit) { private void launchExistingNote(long accountId, long noteId, boolean edit) {
// save state of the fragment in order to resume with the same note and originalNote // save state of the fragment in order to resume with the same note and originalNote
Fragment.SavedState savedState = null; Fragment.SavedState savedState = null;
if (fragment != null) { if (fragment != null) {
savedState = getFragmentManager().saveFragmentInstanceState(fragment); savedState = getFragmentManager().saveFragmentInstanceState(fragment);
} }
if (edit) { if (edit) {
fragment = NoteEditFragment.newInstance(noteId); fragment = NoteEditFragment.newInstance(accountId, noteId);
} else { } else {
fragment = NotePreviewFragment.newInstance(noteId); fragment = NotePreviewFragment.newInstance(accountId, noteId);
} }
if (savedState != null) { if (savedState != null) {
@ -175,10 +183,10 @@ public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragm
close(); close();
return true; return true;
case R.id.menu_preview: case R.id.menu_preview:
launchExistingNote(getNoteId(), false); launchExistingNote(getAccountId(), getNoteId(), false);
return true; return true;
case R.id.menu_edit: case R.id.menu_edit:
launchExistingNote(getNoteId(), true); launchExistingNote(getAccountId(), getNoteId(), true);
return true; return true;
default: default:
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
@ -206,12 +214,17 @@ public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragm
@Override @Override
public void onNoteUpdated(DBNote note) { public void onNoteUpdated(DBNote note) {
ActionBar actionBar = getSupportActionBar(); ActionBar actionBar = Objects.requireNonNull(getSupportActionBar());
if (actionBar != null) { if (note != null) {
actionBar.setTitle(note.getTitle()); actionBar.setTitle(note.getTitle());
if (!note.getCategory().isEmpty()) { if (!note.getCategory().isEmpty()) {
actionBar.setSubtitle(NoteUtil.extendCategory(note.getCategory())); actionBar.setSubtitle(NoteUtil.extendCategory(note.getCategory()));
} }
} else {
// Maybe account is not authenticated -> note == null
Log.e(TAG, "note is null, start NotesListViewActivity");
startActivity(new Intent(this, NotesListViewActivity.class));
finish();
} }
} }
} }

View file

@ -1,5 +1,6 @@
package it.niedermann.owncloud.notes.android.activity; package it.niedermann.owncloud.notes.android.activity;
import android.annotation.SuppressLint;
import android.content.ClipData; import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.os.Bundle; import android.os.Bundle;
@ -16,6 +17,7 @@ import java.util.Objects;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick; import butterknife.OnClick;
import it.niedermann.owncloud.notes.BuildConfig;
import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.R;
public class ExceptionActivity extends AppCompatActivity { public class ExceptionActivity extends AppCompatActivity {
@ -29,6 +31,7 @@ public class ExceptionActivity extends AppCompatActivity {
public static final String KEY_THROWABLE = "T"; public static final String KEY_THROWABLE = "T";
@SuppressLint("SetTextI18n") // only used for logging
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
setContentView(R.layout.activity_exception); setContentView(R.layout.activity_exception);
@ -38,7 +41,7 @@ public class ExceptionActivity extends AppCompatActivity {
throwable.printStackTrace(); throwable.printStackTrace();
Objects.requireNonNull(getSupportActionBar()).setTitle(getString(R.string.simple_error)); Objects.requireNonNull(getSupportActionBar()).setTitle(getString(R.string.simple_error));
this.message.setText(throwable.getMessage()); this.message.setText(throwable.getMessage());
this.stacktrace.setText(getStacktraceOf(throwable)); this.stacktrace.setText("Version: " + BuildConfig.VERSION_NAME + "\n\n" + getStacktraceOf(throwable));
} }
private String getStacktraceOf(Throwable e) { private String getStacktraceOf(Throwable e) {

View file

@ -2,23 +2,26 @@ package it.niedermann.owncloud.notes.android.activity;
import android.app.SearchManager; import android.app.SearchManager;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager; import android.content.pm.ShortcutManager;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.database.sqlite.SQLiteConstraintException;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.drawable.Icon; import android.graphics.drawable.Icon;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.preference.PreferenceManager; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
@ -27,8 +30,11 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.ActionMode; import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.SearchView; import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout; import androidx.drawerlayout.widget.DrawerLayout;
import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.ItemTouchHelper.SimpleCallback; import androidx.recyclerview.widget.ItemTouchHelper.SimpleCallback;
@ -36,8 +42,16 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import com.nextcloud.android.sso.AccountImporter;
import com.nextcloud.android.sso.exceptions.AccountImportCancelledException;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
import com.nextcloud.android.sso.helper.SingleAccountHelper;
import com.nextcloud.android.sso.model.SingleSignOnAccount;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -50,27 +64,28 @@ import it.niedermann.owncloud.notes.model.Category;
import it.niedermann.owncloud.notes.model.DBNote; import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.model.Item; import it.niedermann.owncloud.notes.model.Item;
import it.niedermann.owncloud.notes.model.ItemAdapter; import it.niedermann.owncloud.notes.model.ItemAdapter;
import it.niedermann.owncloud.notes.model.LocalAccount;
import it.niedermann.owncloud.notes.model.LoginStatus;
import it.niedermann.owncloud.notes.model.NavigationAdapter; import it.niedermann.owncloud.notes.model.NavigationAdapter;
import it.niedermann.owncloud.notes.persistence.LoadNotesListTask; import it.niedermann.owncloud.notes.persistence.LoadNotesListTask;
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper; import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper;
import it.niedermann.owncloud.notes.util.ExceptionHandler; import it.niedermann.owncloud.notes.util.ExceptionHandler;
import it.niedermann.owncloud.notes.util.ICallback; import it.niedermann.owncloud.notes.util.ICallback;
import it.niedermann.owncloud.notes.util.NoteUtil; import it.niedermann.owncloud.notes.util.NoteUtil;
import it.niedermann.owncloud.notes.util.NotesClientUtil;
import static it.niedermann.owncloud.notes.android.activity.EditNoteActivity.ACTION_SHORTCUT; import static it.niedermann.owncloud.notes.android.activity.EditNoteActivity.ACTION_SHORTCUT;
import static it.niedermann.owncloud.notes.util.SSOUtil.askForNewAccount;
public class NotesListViewActivity extends AppCompatActivity implements ItemAdapter.NoteClickListener { public class NotesListViewActivity extends AppCompatActivity implements ItemAdapter.NoteClickListener {
private static final String TAG = NotesListViewActivity.class.getSimpleName();
public static final String CREATED_NOTE = "it.niedermann.owncloud.notes.created_notes"; public static final String CREATED_NOTE = "it.niedermann.owncloud.notes.created_notes";
public static final String CREDENTIALS_CHANGED = "it.niedermann.owncloud.notes.CREDENTIALS_CHANGED";
public static final String ADAPTER_KEY_RECENT = "recent"; public static final String ADAPTER_KEY_RECENT = "recent";
public static final String ADAPTER_KEY_STARRED = "starred"; public static final String ADAPTER_KEY_STARRED = "starred";
public static final String ACTION_FAVORITES = "it.niedermann.owncloud.notes.favorites"; public static final String ACTION_FAVORITES = "it.niedermann.owncloud.notes.favorites";
public static final String ACTION_RECENT = "it.niedermann.owncloud.notes.recent"; public static final String ACTION_RECENT = "it.niedermann.owncloud.notes.recent";
private static final String SAVED_STATE_NAVIGATION_SELECTION = "navigationSelection"; private static final String SAVED_STATE_NAVIGATION_SELECTION = "navigationSelection";
private static final String SAVED_STATE_NAVIGATION_ADAPTER_SLECTION = "navigationAdapterSelection"; private static final String SAVED_STATE_NAVIGATION_ADAPTER_SLECTION = "navigationAdapterSelection";
private static final String SAVED_STATE_NAVIGATION_OPEN = "navigationOpen"; private static final String SAVED_STATE_NAVIGATION_OPEN = "navigationOpen";
@ -80,11 +95,28 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
private final static int server_settings = 2; private final static int server_settings = 2;
private final static int about = 3; private final static int about = 3;
/**
* Used to detect the onResume() call after the import dialog has been displayed.
* https://github.com/stefan-niedermann/nextcloud-notes/pull/599/commits/f40eab402d122f113020200751894fa39c8b9fcc#r334239634
*/
private boolean notAuthorizedAccountHandled = false;
private LocalAccount localAccount;
@BindView(R.id.coordinatorLayout)
CoordinatorLayout coordinatorLayout;
@BindView(R.id.accountNavigation)
LinearLayout accountNavigation;
@BindView(R.id.accountChooser)
LinearLayout accountChooser;
@BindView(R.id.notesListActivityActionBar) @BindView(R.id.notesListActivityActionBar)
Toolbar toolbar; Toolbar toolbar;
@BindView(R.id.drawerLayout) @BindView(R.id.drawerLayout)
DrawerLayout drawerLayout; DrawerLayout drawerLayout;
@BindView(R.id.current_account_image)
AppCompatImageView currentAccountImage;
@BindView(R.id.header_view)
RelativeLayout headerView;
@BindView(R.id.account) @BindView(R.id.account)
TextView account; TextView account;
@BindView(R.id.swiperefreshlayout) @BindView(R.id.swiperefreshlayout)
@ -97,6 +129,10 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
RecyclerView listNavigationMenu; RecyclerView listNavigationMenu;
@BindView(R.id.recycler_view) @BindView(R.id.recycler_view)
RecyclerView listView; RecyclerView listView;
@BindView(R.id.empty_content_view)
RelativeLayout emptyContentView;
@BindView(R.id.progress_circular)
ProgressBar progressBar;
private ActionBarDrawerToggle drawerToggle; private ActionBarDrawerToggle drawerToggle;
private ItemAdapter adapter = null; private ItemAdapter adapter = null;
@ -122,39 +158,45 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
if (!shortcutManager.isRateLimitingActive()) { if (!shortcutManager.isRateLimitingActive()) {
List<ShortcutInfo> newShortcuts = new ArrayList<>(); List<ShortcutInfo> newShortcuts = new ArrayList<>();
for (DBNote note : db.getRecentNotes()) { for (DBNote note : db.getRecentNotes(localAccount.getId())) {
Intent intent = new Intent(getApplicationContext(), EditNoteActivity.class); if (!TextUtils.isEmpty(note.getTitle())) {
intent.putExtra(EditNoteActivity.PARAM_NOTE_ID, note.getId()); Intent intent = new Intent(getApplicationContext(), EditNoteActivity.class);
intent.setAction(ACTION_SHORTCUT); intent.putExtra(EditNoteActivity.PARAM_NOTE_ID, note.getId());
intent.setAction(ACTION_SHORTCUT);
newShortcuts.add(new ShortcutInfo.Builder(getApplicationContext(), note.getId() + "") newShortcuts.add(new ShortcutInfo.Builder(getApplicationContext(), note.getId() + "")
.setShortLabel(note.getTitle()) .setShortLabel(note.getTitle() + "")
.setIcon(Icon.createWithResource(getApplicationContext(), note.isFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp)) .setIcon(Icon.createWithResource(getApplicationContext(), note.isFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp))
.setIntent(intent) .setIntent(intent)
.build()); .build());
} else {
// Prevent crash https://github.com/stefan-niedermann/nextcloud-notes/issues/613
Log.e(TAG, "shortLabel cannot be empty " + note);
}
} }
Log.d(getClass().getSimpleName(), "Update dynamic shortcuts"); Log.d(TAG, "Update dynamic shortcuts");
shortcutManager.removeAllDynamicShortcuts(); shortcutManager.removeAllDynamicShortcuts();
shortcutManager.addDynamicShortcuts(newShortcuts); shortcutManager.addDynamicShortcuts(newShortcuts);
} }
} }
}).run(); }).start();
} }
@Override @Override
public void onScheduled() { public void onScheduled() {
} }
}; };
private boolean accountChooserActive;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler(this)); Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler(this));
// First Run Wizard
if (!NoteServerSyncHelper.isConfigured(this)) { setContentView(R.layout.drawer_layout);
Intent settingsIntent = new Intent(this, SettingsActivity.class); ButterKnife.bind(this);
startActivityForResult(settingsIntent, server_settings);
}
String categoryAdapterSelectedItem = ADAPTER_KEY_RECENT; String categoryAdapterSelectedItem = ADAPTER_KEY_RECENT;
if (savedInstanceState == null) { if (savedInstanceState == null) {
if (ACTION_RECENT.equals(getIntent().getAction())) { if (ACTION_RECENT.equals(getIntent().getAction())) {
@ -169,24 +211,35 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
categoryAdapterSelectedItem = savedInstanceState.getString(SAVED_STATE_NAVIGATION_ADAPTER_SLECTION); categoryAdapterSelectedItem = savedInstanceState.getString(SAVED_STATE_NAVIGATION_ADAPTER_SLECTION);
} }
setContentView(R.layout.drawer_layout);
ButterKnife.bind(this);
db = NoteSQLiteOpenHelper.getInstance(this); db = NoteSQLiteOpenHelper.getInstance(this);
setupHeader();
setupActionBar(); setupActionBar();
setupNotesList();
setupNavigationList(categoryAdapterSelectedItem); setupNavigationList(categoryAdapterSelectedItem);
setupNavigationMenu(); setupNavigationMenu();
setupNotesList();
} }
@Override @Override
protected void onResume() { protected void onResume() {
// refresh and sync every time the activity gets visible try {
refreshLists(); String ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(getApplicationContext()).name;
db.getNoteServerSyncHelper().addCallbackPull(syncCallBack); if (localAccount == null || !localAccount.getAccountName().equals(ssoAccount)) {
if (db.getNoteServerSyncHelper().isSyncPossible()) { selectAccount(SingleAccountHelper.getCurrentSingleSignOnAccount(getApplicationContext()).name);
synchronize(); }
} catch (NoCurrentAccountSelectedException | NextcloudFilesAppAccountNotFoundException e) {
if (!notAuthorizedAccountHandled) {
handleNotAuthorizedAccount();
}
}
// refresh and sync every time the activity gets
if (localAccount != null) {
refreshLists();
db.getNoteServerSyncHelper().addCallbackPull(syncCallBack);
if (db.getNoteServerSyncHelper().isSyncPossible()) {
synchronize();
}
} }
super.onResume(); super.onResume();
} }
@ -198,17 +251,86 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
} }
@Override @Override
public void onConfigurationChanged(Configuration newConfig) { public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig); super.onConfigurationChanged(newConfig);
drawerToggle.syncState(); drawerToggle.syncState();
} }
@Override @Override
protected void onSaveInstanceState(Bundle outState) { protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
outState.putSerializable(SAVED_STATE_NAVIGATION_SELECTION, navigationSelection); if (localAccount != null) {
outState.putString(SAVED_STATE_NAVIGATION_ADAPTER_SLECTION, adapterCategories.getSelectedItem()); outState.putSerializable(SAVED_STATE_NAVIGATION_SELECTION, navigationSelection);
outState.putString(SAVED_STATE_NAVIGATION_OPEN, navigationOpen); outState.putString(SAVED_STATE_NAVIGATION_ADAPTER_SLECTION, adapterCategories.getSelectedItem());
outState.putString(SAVED_STATE_NAVIGATION_OPEN, navigationOpen);
}
}
private void selectAccount(String accountName) {
fabCreate.hide();
SingleAccountHelper.setCurrentAccount(getApplicationContext(), accountName);
localAccount = db.getLocalAccountByAccountName(accountName);
try {
db.getNoteServerSyncHelper().updateAccount();
synchronize();
refreshLists();
fabCreate.show();
} catch (NextcloudFilesAppAccountNotFoundException e) {
handleNotAuthorizedAccount();
}
setupHeader();
setupNavigationList(ADAPTER_KEY_RECENT);
updateUsernameInDrawer();
}
private void handleNotAuthorizedAccount() {
fabCreate.hide();
swipeRefreshLayout.setRefreshing(false);
askForNewAccount(this);
notAuthorizedAccountHandled = true;
}
private void setupHeader() {
accountChooser.removeAllViews();
for (LocalAccount account : db.getAccounts()) {
View v = getLayoutInflater().inflate(R.layout.item_account, null);
((TextView) v.findViewById(R.id.accountItemLabel)).setText(account.getAccountName());
Glide
.with(this)
.load(account.getUrl() + "/index.php/avatar/" + Uri.encode(account.getUserName()) + "/64")
.error(R.drawable.ic_account_circle_grey_24dp)
.apply(RequestOptions.circleCropTransform())
.into(((ImageView) v.findViewById(R.id.accountItemAvatar)));
v.setOnClickListener(clickedView -> {
clickHeader();
drawerLayout.closeDrawer(GravityCompat.START);
selectAccount(account.getAccountName());
});
v.findViewById(R.id.delete).setOnClickListener(clickedView -> {
db.deleteAccount(account.getId());
if (account.getId() == localAccount.getId()) {
List<LocalAccount> remainingAccounts = db.getAccounts();
if (remainingAccounts.size() > 0) {
localAccount = remainingAccounts.get(0);
selectAccount(localAccount.getAccountName());
} else {
selectAccount(null);
askForNewAccount(this);
}
}
setupHeader();
clickHeader();
drawerLayout.closeDrawer(GravityCompat.START);
});
accountChooser.addView(v);
}
View addButton = getLayoutInflater().inflate(R.layout.item_account, null);
((TextView) addButton.findViewById(R.id.accountItemLabel)).setText(getString(R.string.add_account));
((AppCompatImageView) addButton.findViewById(R.id.accountItemAvatar)).setImageResource(R.drawable.ic_person_add_grey600_24dp);
addButton.setOnClickListener((btn) -> askForNewAccount(this));
addButton.findViewById(R.id.delete).setVisibility(View.GONE);
accountChooser.addView(addButton);
headerView.setOnClickListener(view -> clickHeader());
} }
private void setupActionBar() { private void setupActionBar() {
@ -220,13 +342,24 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
private void setupNotesList() { private void setupNotesList() {
initList(); initList();
((RecyclerView) findViewById(R.id.recycler_view)).addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
if (dy > 0)
fabCreate.hide();
else if (dy < 0)
fabCreate.show();
}
});
// Pull to Refresh // Pull to Refresh
swipeRefreshLayout.setOnRefreshListener(() -> { swipeRefreshLayout.setOnRefreshListener(() -> {
if (db.getNoteServerSyncHelper().isSyncPossible()) { if (db.getNoteServerSyncHelper().isSyncPossible()) {
synchronize(); synchronize();
} else { } else {
swipeRefreshLayout.setRefreshing(false); swipeRefreshLayout.setRefreshing(false);
Toast.makeText(getApplicationContext(), getString(R.string.error_sync, getString(NotesClientUtil.LoginStatus.NO_NETWORK.str)), Toast.LENGTH_LONG).show(); Toast.makeText(getApplicationContext(), getString(R.string.error_sync, getString(LoginStatus.NO_NETWORK.str)), Toast.LENGTH_LONG).show();
} }
}); });
@ -251,11 +384,11 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
adapterCategories.setSelectedItem(item.id); adapterCategories.setSelectedItem(item.id);
// update current selection // update current selection
if (itemRecent == item) { if (itemRecent.equals(item)) {
navigationSelection = new Category(null, null); navigationSelection = new Category(null, null);
} else if (itemFavorites == item) { } else if (itemFavorites.equals(item)) {
navigationSelection = new Category(null, true); navigationSelection = new Category(null, true);
} else if (itemUncategorized == item) { } else if (itemUncategorized.equals(item)) {
navigationSelection = new Category("", null); navigationSelection = new Category("", null);
} else { } else {
navigationSelection = new Category(item.label, null); navigationSelection = new Category(item.label, null);
@ -272,7 +405,7 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
// update views // update views
if (closeNavigation) { if (closeNavigation) {
drawerLayout.closeDrawers(); drawerLayout.closeDrawer(GravityCompat.START);
} }
refreshLists(true); refreshLists(true);
} }
@ -294,10 +427,25 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
listNavigationCategories.setAdapter(adapterCategories); listNavigationCategories.setAdapter(adapterCategories);
} }
private void clickHeader() {
if (this.accountChooserActive) {
accountChooser.setVisibility(View.GONE);
accountNavigation.setVisibility(View.VISIBLE);
} else {
accountChooser.setVisibility(View.VISIBLE);
accountNavigation.setVisibility(View.GONE);
}
this.accountChooserActive = !this.accountChooserActive;
}
private class LoadCategoryListTask extends AsyncTask<Void, Void, List<NavigationAdapter.NavigationItem>> { private class LoadCategoryListTask extends AsyncTask<Void, Void, List<NavigationAdapter.NavigationItem>> {
@Override @Override
protected List<NavigationAdapter.NavigationItem> doInBackground(Void... voids) { protected List<NavigationAdapter.NavigationItem> doInBackground(Void... voids) {
List<NavigationAdapter.NavigationItem> categories = db.getCategories(); if (localAccount == null) {
return new ArrayList<>();
}
List<NavigationAdapter.NavigationItem> categories = db.getCategories(localAccount.getId());
if (!categories.isEmpty() && categories.get(0).label.isEmpty()) { if (!categories.isEmpty() && categories.get(0).label.isEmpty()) {
itemUncategorized = categories.get(0); itemUncategorized = categories.get(0);
itemUncategorized.label = getString(R.string.action_uncategorized); itemUncategorized.label = getString(R.string.action_uncategorized);
@ -306,7 +454,7 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
itemUncategorized = null; itemUncategorized = null;
} }
Map<String, Integer> favorites = db.getFavoritesCount(); Map<String, Integer> favorites = db.getFavoritesCount(localAccount.getId());
int numFavorites = favorites.containsKey("1") ? favorites.get("1") : 0; int numFavorites = favorites.containsKey("1") ? favorites.get("1") : 0;
int numNonFavorites = favorites.containsKey("0") ? favorites.get("0") : 0; int numNonFavorites = favorites.containsKey("0") ? favorites.get("0") : 0;
itemFavorites.count = numFavorites; itemFavorites.count = numFavorites;
@ -386,16 +534,14 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
NavigationAdapter adapterMenu = new NavigationAdapter(new NavigationAdapter.ClickListener() { NavigationAdapter adapterMenu = new NavigationAdapter(new NavigationAdapter.ClickListener() {
@Override @Override
public void onItemClick(NavigationAdapter.NavigationItem item) { public void onItemClick(NavigationAdapter.NavigationItem item) {
if (item == itemSettings) { if (itemSettings.equals(item)) {
Intent settingsIntent = new Intent(getApplicationContext(), PreferencesActivity.class); Intent settingsIntent = new Intent(getApplicationContext(), PreferencesActivity.class);
startActivityForResult(settingsIntent, server_settings); startActivityForResult(settingsIntent, server_settings);
} else if (item == itemAbout) { } else if (itemAbout.equals(item)) {
Intent aboutIntent = new Intent(getApplicationContext(), AboutActivity.class); Intent aboutIntent = new Intent(getApplicationContext(), AboutActivity.class);
startActivityForResult(aboutIntent, about); startActivityForResult(aboutIntent, about);
} else if (item == itemTrashbin) { } else if (itemTrashbin.equals(item) && localAccount != null) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(localAccount.getUrl() + "/index.php/apps/files/?dir=/&view=trashbin")));
String url = preferences.getString(SettingsActivity.SETTINGS_URL, SettingsActivity.DEFAULT_SETTINGS);
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url + "index.php/apps/files/?dir=/&view=trashbin")));
} }
} }
@ -407,12 +553,6 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
this.updateUsernameInDrawer(); this.updateUsernameInDrawer();
final NotesListViewActivity that = this;
this.account.setOnClickListener((View v) -> {
Intent settingsIntent = new Intent(that, SettingsActivity.class);
startActivityForResult(settingsIntent, server_settings);
});
adapterMenu.setItems(itemsMenu); adapterMenu.setItems(itemsMenu);
listNavigationMenu.setAdapter(adapterMenu); listNavigationMenu.setAdapter(adapterMenu);
} }
@ -454,10 +594,10 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
db.deleteNoteAndSync((dbNote).getId()); db.deleteNoteAndSync((dbNote).getId());
adapter.remove(dbNote); adapter.remove(dbNote);
refreshLists(); refreshLists();
Log.v("Note", "Item deleted through swipe ----------------------------------------------"); Log.v(TAG, "Item deleted through swipe ----------------------------------------------");
Snackbar.make(swipeRefreshLayout, R.string.action_note_deleted, Snackbar.LENGTH_LONG) Snackbar.make(swipeRefreshLayout, R.string.action_note_deleted, Snackbar.LENGTH_LONG)
.setAction(R.string.action_undo, (View v) -> { .setAction(R.string.action_undo, (View v) -> {
db.addNoteAndSync(dbNote); db.addNoteAndSync(dbNote.getAccountId(), dbNote);
refreshLists(); refreshLists();
Snackbar.make(swipeRefreshLayout, R.string.action_note_restored, Snackbar.LENGTH_SHORT) Snackbar.make(swipeRefreshLayout, R.string.action_note_restored, Snackbar.LENGTH_SHORT)
.show(); .show();
@ -496,7 +636,15 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
} }
private void refreshLists(final boolean scrollToTop) { private void refreshLists(final boolean scrollToTop) {
String subtitle = ""; if (localAccount == null) {
fabCreate.hide();
adapter.removeAll();
return;
}
emptyContentView.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
fabCreate.show();
String subtitle;
if (navigationSelection.category != null) { if (navigationSelection.category != null) {
if (navigationSelection.category.isEmpty()) { if (navigationSelection.category.isEmpty()) {
subtitle = getString(R.string.action_uncategorized); subtitle = getString(R.string.action_uncategorized);
@ -517,11 +665,17 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
LoadNotesListTask.NotesLoadedListener callback = (List<Item> notes, boolean showCategory) -> { LoadNotesListTask.NotesLoadedListener callback = (List<Item> notes, boolean showCategory) -> {
adapter.setShowCategory(showCategory); adapter.setShowCategory(showCategory);
adapter.setItemList(notes); adapter.setItemList(notes);
progressBar.setVisibility(View.GONE);
if (notes.size() > 0) {
emptyContentView.setVisibility(View.GONE);
} else {
emptyContentView.setVisibility(View.VISIBLE);
}
if (scrollToTop) { if (scrollToTop) {
listView.scrollToPosition(0); listView.scrollToPosition(0);
} }
}; };
new LoadNotesListTask(getApplicationContext(), callback, navigationSelection, query).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); new LoadNotesListTask(localAccount.getId(), getApplicationContext(), callback, navigationSelection, query).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new LoadCategoryListTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); new LoadCategoryListTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} }
@ -560,9 +714,7 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
if (currentVisibility == View.VISIBLE) { if (currentVisibility == View.VISIBLE) {
fabCreate.hide(); fabCreate.hide();
} else { } else {
new Handler().postDelayed(() -> { new Handler().postDelayed(() -> fabCreate.show(), 150);
fabCreate.show();
}, 150);
} }
oldVisibility = currentVisibility; oldVisibility = currentVisibility;
@ -594,6 +746,12 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
super.onNewIntent(intent); super.onNewIntent(intent);
} }
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
AccountImporter.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
/** /**
* Handles the Results of started Sub Activities (Created Note, Edited Note) * Handles the Results of started Sub Activities (Created Note, Edited Note)
* *
@ -603,6 +761,8 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
*/ */
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Check which request we're responding to // Check which request we're responding to
if (requestCode == create_note_cmd) { if (requestCode == create_note_cmd) {
// Make sure the request was successful // Make sure the request was successful
@ -615,10 +775,10 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
if (createdNote != null) { if (createdNote != null) {
adapter.add(createdNote); adapter.add(createdNote);
} else { } else {
Log.w(NotesListViewActivity.class.getSimpleName(), "createdNote is null"); Log.w(TAG, "createdNote is null");
} }
} else { } else {
Log.w(NotesListViewActivity.class.getSimpleName(), "bundle is null"); Log.w(TAG, "bundle is null");
} }
} }
listView.scrollToPosition(0); listView.scrollToPosition(0);
@ -626,20 +786,51 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
// Recreate activity completely, because theme switchting makes problems when only invalidating the views. // Recreate activity completely, because theme switchting makes problems when only invalidating the views.
// @see https://github.com/stefan-niedermann/nextcloud-notes/issues/529 // @see https://github.com/stefan-niedermann/nextcloud-notes/issues/529
recreate(); recreate();
} else {
try {
AccountImporter.onActivityResult(requestCode, resultCode, data, this, (SingleSignOnAccount account) -> {
Log.v(TAG, "Added account: " + "name:" + account.name + ", " + account.url + ", userId" + account.userId);
try {
db.addAccount(account.url, account.userId, account.name);
} catch (SQLiteConstraintException e) {
if (db.getAccounts().size() > 1) { // TODO ideally only show snackbar when this is a not migrated account
Snackbar.make(coordinatorLayout, R.string.account_already_imported, Snackbar.LENGTH_LONG).show();
}
}
selectAccount(account.name);
this.accountChooserActive = false;
accountChooser.setVisibility(View.GONE);
accountNavigation.setVisibility(View.VISIBLE);
drawerLayout.closeDrawer(GravityCompat.START);
});
} catch (AccountImportCancelledException e) {
Log.i(TAG, "AccountImport has been cancelled.");
}
} }
} }
private void updateUsernameInDrawer() { private void updateUsernameInDrawer() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); try {
String username = preferences.getString(SettingsActivity.SETTINGS_USERNAME, SettingsActivity.DEFAULT_SETTINGS); String url = localAccount.getUrl();
String url = preferences.getString(SettingsActivity.SETTINGS_URL, SettingsActivity.DEFAULT_SETTINGS); if (url != null) {
if (url != null) { this.account.setText(localAccount.getAccountName());
url = url.replace("https://", "").replace("http://", ""); Glide
} else { .with(this)
Log.w(NotesListViewActivity.class.getSimpleName(), "url is null"); .load(url + "/index.php/avatar/" + Uri.encode(localAccount.getUserName()) + "/64")
} .error(R.mipmap.ic_launcher)
if (!SettingsActivity.DEFAULT_SETTINGS.equals(username) && !SettingsActivity.DEFAULT_SETTINGS.equals(url)) { .apply(RequestOptions.circleCropTransform())
this.account.setText(username + "@" + url.substring(0, url.length() - 1)); .into(this.currentAccountImage);
} else {
Log.w(TAG, "url is null");
}
} catch (NullPointerException e) { // No local account - show generic header
this.account.setText(R.string.app_name_long);
Glide
.with(this)
.load(R.mipmap.ic_launcher)
.apply(RequestOptions.circleCropTransform())
.into(this.currentAccountImage);
Log.w(TAG, "Tried to update username in drawer, but localAccount was null");
} }
} }
@ -653,7 +844,7 @@ public class NotesListViewActivity extends AppCompatActivity implements ItemAdap
v.setSelected(true); v.setSelected(true);
} }
int size = adapter.getSelected().size(); int size = adapter.getSelected().size();
mActionMode.setTitle(String.valueOf(getResources().getQuantityString(R.plurals.ab_selected, size, size))); mActionMode.setTitle(getResources().getQuantityString(R.plurals.ab_selected, size, size));
int checkedItemCount = adapter.getSelected().size(); int checkedItemCount = adapter.getSelected().size();
boolean hasCheckedItems = checkedItemCount > 0; boolean hasCheckedItems = checkedItemCount > 0;

View file

@ -62,10 +62,12 @@ public class SelectSingleNoteActivity extends NotesListViewActivity {
finish(); finish();
} }
assert extras != null;
int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
SharedPreferences.Editor sp = PreferenceManager.getDefaultSharedPreferences(this).edit(); SharedPreferences.Editor sp = PreferenceManager.getDefaultSharedPreferences(this).edit();
sp.putLong(SingleNoteWidget.WIDGET_KEY + appWidgetId, noteID); sp.putLong(SingleNoteWidget.WIDGET_KEY + appWidgetId, noteID);
sp.putLong(SingleNoteWidget.ACCOUNT_ID_KEY + appWidgetId, note.getAccountId());
sp.putBoolean(SingleNoteWidget.DARK_THEME_KEY + appWidgetId, Notes.getAppTheme(getApplicationContext())); sp.putBoolean(SingleNoteWidget.DARK_THEME_KEY + appWidgetId, Notes.getAppTheme(getApplicationContext()));
sp.apply(); sp.apply();

View file

@ -1,287 +0,0 @@
package it.niedermann.owncloud.notes.android.activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import com.google.android.material.textfield.TextInputLayout;
import at.bitfire.cert4android.CustomCertManager;
import butterknife.BindView;
import butterknife.ButterKnife;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper;
import it.niedermann.owncloud.notes.util.ExceptionHandler;
import it.niedermann.owncloud.notes.util.NotesClientUtil;
import it.niedermann.owncloud.notes.util.NotesClientUtil.LoginStatus;
/**
* Allows to set Settings like URL, Username and Password for Server-Synchronization
* Created by stefan on 22.09.15.
*/
public class SettingsActivity extends AppCompatActivity {
public static final String SETTINGS_URL = "settingsUrl";
public static final String SETTINGS_USERNAME = "settingsUsername";
public static final String SETTINGS_PASSWORD = "settingsPassword";
public static final String SETTINGS_KEY_ETAG = "notes_last_etag";
public static final String SETTINGS_KEY_LAST_MODIFIED = "notes_last_modified";
public static final String DEFAULT_SETTINGS = "";
public static final int CREDENTIALS_CHANGED = 3;
private SharedPreferences preferences = null;
@BindView(R.id.settings_url)
EditText field_url;
@BindView(R.id.settings_username)
EditText field_username;
@BindView(R.id.settings_password)
EditText field_password;
@BindView(R.id.settings_password_wrapper)
TextInputLayout password_wrapper;
@BindView(R.id.settings_submit)
Button btn_submit;
@BindView(R.id.settings_url_warn_http)
View urlWarnHttp;
private String old_password = "";
private boolean first_run = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler(this));
setContentView(R.layout.activity_settings);
ButterKnife.bind(this);
preferences = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
if (!NoteServerSyncHelper.isConfigured(this)) {
first_run = true;
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
}
}
field_url.setOnFocusChangeListener((View v, boolean hasFocus) -> {
new URLValidatorAsyncTask().execute(NotesClientUtil.formatURL(field_url.getText().toString()));
});
field_url.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String url = NotesClientUtil.formatURL(field_url.getText().toString());
if (NotesClientUtil.isHttp(url)) {
urlWarnHttp.setVisibility(View.VISIBLE);
} else {
urlWarnHttp.setVisibility(View.GONE);
}
handleSubmitButtonEnabled(field_url.getText(), field_username.getText());
}
@Override
public void afterTextChanged(Editable s) {
}
});
field_username.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
handleSubmitButtonEnabled(field_url.getText(), field_username.getText());
}
@Override
public void afterTextChanged(Editable s) {
}
});
// Load current Preferences
field_url.setText(preferences.getString(SETTINGS_URL, DEFAULT_SETTINGS));
field_username.setText(preferences.getString(SETTINGS_USERNAME, DEFAULT_SETTINGS));
old_password = preferences.getString(SETTINGS_PASSWORD, DEFAULT_SETTINGS);
field_password.setOnEditorActionListener((TextView v, int actionId, KeyEvent event) -> {
login();
return true;
});
field_password.setOnFocusChangeListener((View v, boolean hasFocus) -> {
setPasswordHint(hasFocus);
});
setPasswordHint(false);
btn_submit.setEnabled(false);
btn_submit.setOnClickListener((View v) -> {
login();
});
}
private void setPasswordHint(boolean hasFocus) {
boolean unchangedHint = !hasFocus && field_password.getText().toString().isEmpty() && !old_password.isEmpty();
password_wrapper.setHint(getString(unchangedHint ? R.string.settings_password_unchanged : R.string.settings_password));
}
@Override
protected void onResume() {
super.onResume();
// Occurs in this scenario: User opens the app but doesn't configure the server settings, they then add the Create Note widget to home screen and configure
// server settings there. The stale SettingsActivity is then displayed hence finish() here to close it down.
if ((first_run) && (NoteServerSyncHelper.isConfigured(this))) {
finish();
}
}
/**
* Prevent pressing back button on first run
*/
@Override
public void onBackPressed() {
if (!first_run) {
super.onBackPressed();
}
}
private void login() {
String url = field_url.getText().toString().trim();
String username = field_username.getText().toString();
String password = field_password.getText().toString();
if (password.isEmpty()) {
password = old_password;
}
url = NotesClientUtil.formatURL(url);
new LoginValidatorAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url, username, password);
}
private void handleSubmitButtonEnabled(Editable url, Editable username) {
if (field_username.getText().length() > 0 && field_url.getText().length() > 0) {
btn_submit.setEnabled(true);
} else {
btn_submit.setEnabled(false);
}
}
/************************************ Async Tasks ************************************/
/**
* Checks if the given URL returns a valid status code and sets the Check next to the URL-Input Field to visible.
* Created by stefan on 23.09.15.
*/
private class URLValidatorAsyncTask extends AsyncTask<String, Void, Boolean> {
@Override
protected void onPreExecute() {
field_url.setCompoundDrawables(null, null, null, null);
}
@Override
protected Boolean doInBackground(String... params) {
CustomCertManager ccm = NoteServerSyncHelper.getInstance(NoteSQLiteOpenHelper.getInstance(getApplicationContext())).getCustomCertManager();
return NotesClientUtil.isValidURL(ccm, params[0]);
}
@Override
protected void onPostExecute(Boolean o) {
if (o) {
Drawable actionDoneDark = ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_check_grey600_24dp);
actionDoneDark.setBounds( 0, 0, actionDoneDark.getIntrinsicWidth(), actionDoneDark.getIntrinsicHeight() );
field_url.setCompoundDrawables(null, null, actionDoneDark, null);
} else {
field_url.setCompoundDrawables(null, null, null, null);
}
}
}
/**
* If Log-In-Credentials are correct, save Credentials to Shared Preferences and finish First Run Wizard.
*/
private class LoginValidatorAsyncTask extends AsyncTask<String, Void, LoginStatus> {
String url, username, password;
@Override
protected void onPreExecute() {
setInputsEnabled(false);
btn_submit.setText(R.string.settings_submitting);
}
/**
* @param params url, username and password
* @return isValidLogin Boolean
*/
@Override
protected LoginStatus doInBackground(String... params) {
url = params[0];
username = params[1];
password = params[2];
CustomCertManager ccm = NoteServerSyncHelper.getInstance(NoteSQLiteOpenHelper.getInstance(getApplicationContext())).getCustomCertManager();
return NotesClientUtil.isValidLogin(ccm, url, username, password);
}
@Override
protected void onPostExecute(LoginStatus status) {
if (LoginStatus.OK.equals(status)) {
SharedPreferences.Editor editor = preferences.edit();
editor.putString(SETTINGS_URL, url);
editor.putString(SETTINGS_USERNAME, username);
editor.putString(SETTINGS_PASSWORD, password);
editor.remove(SETTINGS_KEY_ETAG);
editor.remove(SETTINGS_KEY_LAST_MODIFIED);
editor.apply();
final Intent data = new Intent();
data.putExtra(NotesListViewActivity.CREDENTIALS_CHANGED, CREDENTIALS_CHANGED);
setResult(RESULT_OK, data);
finish();
} else {
Log.e("Note", "invalid login");
btn_submit.setText(R.string.settings_submit);
setInputsEnabled(true);
Toast.makeText(getApplicationContext(), getString(R.string.error_invalid_login, getString(status.str)), Toast.LENGTH_LONG).show();
}
}
/**
* Sets all Input-Fields and Buttons to enabled or disabled depending on the given boolean.
*
* @param enabled - boolean
*/
private void setInputsEnabled(boolean enabled) {
btn_submit.setEnabled(enabled);
field_url.setEnabled(enabled);
field_username.setEnabled(enabled);
field_password.setEnabled(enabled);
}
}
}

View file

@ -17,8 +17,10 @@ import it.niedermann.owncloud.notes.android.activity.EditNoteActivity;
import it.niedermann.owncloud.notes.android.activity.NotesListViewActivity; import it.niedermann.owncloud.notes.android.activity.NotesListViewActivity;
public class NoteListWidget extends AppWidgetProvider { public class NoteListWidget extends AppWidgetProvider {
private static final String TAG = NoteListWidget.class.getSimpleName();
public static final String WIDGET_MODE_KEY = "NLW_mode"; public static final String WIDGET_MODE_KEY = "NLW_mode";
public static final String WIDGET_CATEGORY_KEY = "NLW_cat"; public static final String WIDGET_CATEGORY_KEY = "NLW_cat";
public static final String ACCOUNT_ID_KEY = "NLW_account";
public static final String DARK_THEME_KEY = "NLW_darkTheme"; public static final String DARK_THEME_KEY = "NLW_darkTheme";
public static final int NLW_DISPLAY_ALL = 0; public static final int NLW_DISPLAY_ALL = 0;
public static final int NLW_DISPLAY_STARRED = 1; public static final int NLW_DISPLAY_STARRED = 1;
@ -111,14 +113,14 @@ public class NoteListWidget extends AppWidgetProvider {
if (intent.getExtras() != null) { if (intent.getExtras() != null) {
updateAppWidget(context, awm, new int[]{intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)}); updateAppWidget(context, awm, new int[]{intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)});
} else { } else {
Log.w(NoteListWidget.class.getSimpleName(), "intent.getExtras() is null"); Log.w(TAG, "intent.getExtras() is null");
} }
} else { } else {
updateAppWidget(context, awm, awm.getAppWidgetIds(new ComponentName(context, NoteListWidget.class))); updateAppWidget(context, awm, awm.getAppWidgetIds(new ComponentName(context, NoteListWidget.class)));
} }
} }
} else { } else {
Log.w(NoteListWidget.class.getSimpleName(), "intent.getAction() is null"); Log.w(TAG, "intent.getAction() is null");
} }
} }
@ -131,6 +133,7 @@ public class NoteListWidget extends AppWidgetProvider {
for (int appWidgetId : appWidgetIds) { for (int appWidgetId : appWidgetIds) {
editor.remove(WIDGET_MODE_KEY + appWidgetId); editor.remove(WIDGET_MODE_KEY + appWidgetId);
editor.remove(WIDGET_CATEGORY_KEY + appWidgetId); editor.remove(WIDGET_CATEGORY_KEY + appWidgetId);
editor.remove(ACCOUNT_ID_KEY + appWidgetId);
editor.remove(DARK_THEME_KEY + appWidgetId); editor.remove(DARK_THEME_KEY + appWidgetId);
} }
@ -144,7 +147,7 @@ public class NoteListWidget extends AppWidgetProvider {
case NoteListWidget.NLW_DISPLAY_STARRED: case NoteListWidget.NLW_DISPLAY_STARRED:
return context.getString(R.string.label_favorites); return context.getString(R.string.label_favorites);
case NoteListWidget.NLW_DISPLAY_CATEGORY: case NoteListWidget.NLW_DISPLAY_CATEGORY:
if (category.equals("")) { if ("".equals(category)) {
return context.getString(R.string.action_uncategorized); return context.getString(R.string.action_uncategorized);
} else { } else {
return category; return category;

View file

@ -7,12 +7,17 @@ import android.content.SharedPreferences;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.widget.Toast; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
import com.nextcloud.android.sso.helper.SingleAccountHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -20,9 +25,9 @@ import java.util.Map;
import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.activity.NotesListViewActivity; import it.niedermann.owncloud.notes.android.activity.NotesListViewActivity;
import it.niedermann.owncloud.notes.model.LocalAccount;
import it.niedermann.owncloud.notes.model.NavigationAdapter; import it.niedermann.owncloud.notes.model.NavigationAdapter;
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper; import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper;
import it.niedermann.owncloud.notes.util.Notes; import it.niedermann.owncloud.notes.util.Notes;
public class NoteListWidgetConfiguration extends AppCompatActivity { public class NoteListWidgetConfiguration extends AppCompatActivity {
@ -30,6 +35,9 @@ public class NoteListWidgetConfiguration extends AppCompatActivity {
private int appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; private int appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
LocalAccount localAccount = null;
private NavigationAdapter adapterCategories; private NavigationAdapter adapterCategories;
private NavigationAdapter.NavigationItem itemRecent, itemFavorites; private NavigationAdapter.NavigationItem itemRecent, itemFavorites;
private NoteSQLiteOpenHelper db = null; private NoteSQLiteOpenHelper db = null;
@ -40,15 +48,16 @@ public class NoteListWidgetConfiguration extends AppCompatActivity {
setResult(RESULT_CANCELED); setResult(RESULT_CANCELED);
setContentView(R.layout.activity_note_list_configuration); setContentView(R.layout.activity_note_list_configuration);
if (!(NoteServerSyncHelper.isConfigured(this))) { db = NoteSQLiteOpenHelper.getInstance(this);
try {
this.localAccount = db.getLocalAccountByAccountName(SingleAccountHelper.getCurrentSingleSignOnAccount(this).name);
} catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
e.printStackTrace();
Toast.makeText(this, R.string.widget_not_logged_in, Toast.LENGTH_LONG).show(); Toast.makeText(this, R.string.widget_not_logged_in, Toast.LENGTH_LONG).show();
// TODO Present user with app login screen // TODO Present user with app login screen
Log.w(TAG, "onCreate: user not logged in"); Log.w(TAG, "onCreate: user not logged in");
finish(); finish();
} }
db = NoteSQLiteOpenHelper.getInstance(this);
final Bundle extras = getIntent().getExtras(); final Bundle extras = getIntent().getExtras();
if (extras != null) { if (extras != null) {
@ -77,9 +86,9 @@ public class NoteListWidgetConfiguration extends AppCompatActivity {
public void onItemClick(NavigationAdapter.NavigationItem item) { public void onItemClick(NavigationAdapter.NavigationItem item) {
SharedPreferences.Editor sp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).edit(); SharedPreferences.Editor sp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).edit();
if (item == itemRecent) { if (itemRecent.equals(item)) {
sp.putInt(NoteListWidget.WIDGET_MODE_KEY + appWidgetId, NoteListWidget.NLW_DISPLAY_ALL); sp.putInt(NoteListWidget.WIDGET_MODE_KEY + appWidgetId, NoteListWidget.NLW_DISPLAY_ALL);
} else if (item == itemFavorites) { } else if (itemFavorites.equals(item)) {
sp.putInt(NoteListWidget.WIDGET_MODE_KEY + appWidgetId, NoteListWidget.NLW_DISPLAY_STARRED); sp.putInt(NoteListWidget.WIDGET_MODE_KEY + appWidgetId, NoteListWidget.NLW_DISPLAY_STARRED);
} else { } else {
String category = ""; String category = "";
@ -90,6 +99,7 @@ public class NoteListWidgetConfiguration extends AppCompatActivity {
sp.putString(NoteListWidget.WIDGET_CATEGORY_KEY + appWidgetId, category); sp.putString(NoteListWidget.WIDGET_CATEGORY_KEY + appWidgetId, category);
} }
sp.putLong(NoteListWidget.ACCOUNT_ID_KEY + appWidgetId, localAccount.getId());
sp.putBoolean(NoteListWidget.DARK_THEME_KEY + appWidgetId, Notes.getAppTheme(getApplicationContext())); sp.putBoolean(NoteListWidget.DARK_THEME_KEY + appWidgetId, Notes.getAppTheme(getApplicationContext()));
sp.apply(); sp.apply();
@ -116,15 +126,17 @@ public class NoteListWidgetConfiguration extends AppCompatActivity {
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
new LoadCategoryListTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); new LoadCategoryListTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} }
private class LoadCategoryListTask extends AsyncTask<Void, Void, List<NavigationAdapter.NavigationItem>> { private class LoadCategoryListTask extends AsyncTask<Void, Void, List<NavigationAdapter.NavigationItem>> {
@Override @Override
protected List<NavigationAdapter.NavigationItem> doInBackground(Void... voids) { protected List<NavigationAdapter.NavigationItem> doInBackground(Void... voids) {
if (localAccount == null) {
return new ArrayList<>();
}
NavigationAdapter.NavigationItem itemUncategorized; NavigationAdapter.NavigationItem itemUncategorized;
List<NavigationAdapter.NavigationItem> categories = db.getCategories(); List<NavigationAdapter.NavigationItem> categories = db.getCategories(localAccount.getId());
if (!categories.isEmpty() && categories.get(0).label.isEmpty()) { if (!categories.isEmpty() && categories.get(0).label.isEmpty()) {
itemUncategorized = categories.get(0); itemUncategorized = categories.get(0);
@ -132,7 +144,7 @@ public class NoteListWidgetConfiguration extends AppCompatActivity {
itemUncategorized.icon = NavigationAdapter.ICON_NOFOLDER; itemUncategorized.icon = NavigationAdapter.ICON_NOFOLDER;
} }
Map<String, Integer> favorites = db.getFavoritesCount(); Map<String, Integer> favorites = db.getFavoritesCount(localAccount.getId());
int numFavorites = favorites.containsKey("1") ? favorites.get("1") : 0; int numFavorites = favorites.containsKey("1") ? favorites.get("1") : 0;
int numNonFavorites = favorites.containsKey("0") ? favorites.get("0") : 0; int numNonFavorites = favorites.containsKey("0") ? favorites.get("0") : 0;
itemFavorites.count = numFavorites; itemFavorites.count = numFavorites;

View file

@ -20,21 +20,21 @@ import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
public class NoteListWidgetFactory implements RemoteViewsService.RemoteViewsFactory { public class NoteListWidgetFactory implements RemoteViewsService.RemoteViewsFactory {
private final Context context; private final Context context;
private final int displayMode; private final int displayMode;
private final int appWidgetId;
private final boolean darkTheme; private final boolean darkTheme;
private String category; private String category;
private final SharedPreferences sp;
private NoteSQLiteOpenHelper db; private NoteSQLiteOpenHelper db;
private List<DBNote> dbNotes; private List<DBNote> dbNotes;
private long accountId;
NoteListWidgetFactory(Context context, Intent intent) { NoteListWidgetFactory(Context context, Intent intent) {
this.context = context; this.context = context;
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, final int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID); AppWidgetManager.INVALID_APPWIDGET_ID);
sp = PreferenceManager.getDefaultSharedPreferences(this.context); final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this.context);
displayMode = sp.getInt(NoteListWidget.WIDGET_MODE_KEY + appWidgetId, -1); displayMode = sp.getInt(NoteListWidget.WIDGET_MODE_KEY + appWidgetId, -1);
darkTheme = sp.getBoolean(NoteListWidget.DARK_THEME_KEY + appWidgetId, false); darkTheme = sp.getBoolean(NoteListWidget.DARK_THEME_KEY + appWidgetId, false);
category = sp.getString(NoteListWidget.WIDGET_CATEGORY_KEY + appWidgetId, ""); category = sp.getString(NoteListWidget.WIDGET_CATEGORY_KEY + appWidgetId, "");
accountId = sp.getLong(NoteListWidget.ACCOUNT_ID_KEY + appWidgetId, -1);
} }
@Override @Override
@ -44,12 +44,16 @@ public class NoteListWidgetFactory implements RemoteViewsService.RemoteViewsFact
@Override @Override
public void onDataSetChanged() { public void onDataSetChanged() {
if (displayMode == NoteListWidget.NLW_DISPLAY_ALL) { try {
dbNotes = db.getNotes(); if (displayMode == NoteListWidget.NLW_DISPLAY_ALL) {
} else if (displayMode == NoteListWidget.NLW_DISPLAY_STARRED) { dbNotes = db.getNotes(accountId);
dbNotes = db.searchNotes(null,null, true); } else if (displayMode == NoteListWidget.NLW_DISPLAY_STARRED) {
} else if (displayMode == NoteListWidget.NLW_DISPLAY_CATEGORY) { dbNotes = db.searchNotes(accountId, null, null, true);
dbNotes = db.searchNotes(null, category, null); } else if (displayMode == NoteListWidget.NLW_DISPLAY_CATEGORY) {
dbNotes = db.searchNotes(accountId, null, category, null);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} }
} }
@ -85,6 +89,7 @@ public class NoteListWidgetFactory implements RemoteViewsService.RemoteViewsFact
final Bundle extras = new Bundle(); final Bundle extras = new Bundle();
extras.putLong(EditNoteActivity.PARAM_NOTE_ID, note.getId()); extras.putLong(EditNoteActivity.PARAM_NOTE_ID, note.getId());
extras.putLong(EditNoteActivity.PARAM_ACCOUNT_ID, note.getAccountId());
fillInIntent.putExtras(extras); fillInIntent.putExtras(extras);
fillInIntent.setData(Uri.parse(fillInIntent.toUri(Intent.URI_INTENT_SCHEME))); fillInIntent.setData(Uri.parse(fillInIntent.toUri(Intent.URI_INTENT_SCHEME)));

View file

@ -13,12 +13,13 @@ import android.widget.RemoteViews;
import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.activity.EditNoteActivity; import it.niedermann.owncloud.notes.android.activity.EditNoteActivity;
import it.niedermann.owncloud.notes.android.fragment.BaseNoteFragment;
public class SingleNoteWidget extends AppWidgetProvider { public class SingleNoteWidget extends AppWidgetProvider {
private static boolean darkTheme;
public static final String DARK_THEME_KEY = "SNW_darkTheme"; public static final String DARK_THEME_KEY = "SNW_darkTheme";
public static final String WIDGET_KEY = "single_note_widget"; public static final String WIDGET_KEY = "single_note_widget";
public static final String ACCOUNT_ID_KEY = "SNW_accountId";
static void updateAppWidget(Context context, AppWidgetManager awm, int[] appWidgetIds) { static void updateAppWidget(Context context, AppWidgetManager awm, int[] appWidgetIds) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
@ -31,7 +32,8 @@ public class SingleNoteWidget extends AppWidgetProvider {
return; return;
} }
darkTheme = sp.getBoolean(DARK_THEME_KEY + appWidgetId, false); boolean darkTheme = sp.getBoolean(DARK_THEME_KEY + appWidgetId, false);
templateIntent.putExtra(BaseNoteFragment.PARAM_ACCOUNT_ID, sp.getLong(ACCOUNT_ID_KEY + appWidgetId, -1));
PendingIntent templatePendingIntent = PendingIntent.getActivity(context, appWidgetId, templateIntent, PendingIntent templatePendingIntent = PendingIntent.getActivity(context, appWidgetId, templateIntent,
PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.FLAG_UPDATE_CURRENT);
@ -55,7 +57,6 @@ public class SingleNoteWidget extends AppWidgetProvider {
views.setEmptyView(R.id.single_note_widget_lv, R.id.widget_single_note_placeholder_tv); views.setEmptyView(R.id.single_note_widget_lv, R.id.widget_single_note_placeholder_tv);
awm.notifyAppWidgetViewDataChanged(appWidgetId, R.id.single_note_widget_lv); awm.notifyAppWidgetViewDataChanged(appWidgetId, R.id.single_note_widget_lv);
} }
awm.updateAppWidget(appWidgetId, views); awm.updateAppWidget(appWidgetId, views);
} }
} }
@ -82,7 +83,8 @@ public class SingleNoteWidget extends AppWidgetProvider {
for (int appWidgetId : appWidgetIds) { for (int appWidgetId : appWidgetIds) {
editor.remove(WIDGET_KEY + appWidgetId); editor.remove(WIDGET_KEY + appWidgetId);
editor.remove(NoteListWidget.DARK_THEME_KEY + appWidgetId); editor.remove(DARK_THEME_KEY + appWidgetId);
editor.remove(ACCOUNT_ID_KEY + appWidgetId);
} }
editor.apply(); editor.apply();

View file

@ -54,7 +54,10 @@ public class SingleNoteWidgetFactory implements RemoteViewsService.RemoteViewsFa
long noteID = sp.getLong(SingleNoteWidget.WIDGET_KEY + appWidgetId, -1); long noteID = sp.getLong(SingleNoteWidget.WIDGET_KEY + appWidgetId, -1);
if (noteID >= 0) { if (noteID >= 0) {
note = db.getNote(noteID); Log.v(TAG, "Fetch note for account " + SingleNoteWidget.ACCOUNT_ID_KEY + appWidgetId);
Log.v(TAG, "Fetch note for account " + sp.getLong(SingleNoteWidget.ACCOUNT_ID_KEY + appWidgetId, -1));
Log.v(TAG, "Fetch note with id " + noteID);
note = db.getNote(sp.getLong(SingleNoteWidget.ACCOUNT_ID_KEY + appWidgetId, -1), noteID);
if (note == null) { if (note == null) {
Log.e(TAG, "Error: note not found"); Log.e(TAG, "Error: note not found");
@ -95,6 +98,7 @@ public class SingleNoteWidgetFactory implements RemoteViewsService.RemoteViewsFa
final Bundle extras = new Bundle(); final Bundle extras = new Bundle();
extras.putLong(EditNoteActivity.PARAM_NOTE_ID, note.getId()); extras.putLong(EditNoteActivity.PARAM_NOTE_ID, note.getId());
extras.putLong(EditNoteActivity.PARAM_ACCOUNT_ID, note.getAccountId());
fillInIntent.putExtras(extras); fillInIntent.putExtras(extras);
fillInIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); fillInIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
if (darkTheme) { if (darkTheme) {

View file

@ -28,10 +28,15 @@ import androidx.appcompat.widget.ShareActionProvider;
import androidx.core.view.MenuItemCompat; import androidx.core.view.MenuItemCompat;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
import com.nextcloud.android.sso.helper.SingleAccountHelper;
import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.activity.EditNoteActivity; import it.niedermann.owncloud.notes.android.activity.EditNoteActivity;
import it.niedermann.owncloud.notes.model.CloudNote; import it.niedermann.owncloud.notes.model.CloudNote;
import it.niedermann.owncloud.notes.model.DBNote; import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.model.LocalAccount;
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper; import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
import it.niedermann.owncloud.notes.util.DisplayUtils; import it.niedermann.owncloud.notes.util.DisplayUtils;
import it.niedermann.owncloud.notes.util.ICallback; import it.niedermann.owncloud.notes.util.ICallback;
@ -41,14 +46,11 @@ import static it.niedermann.owncloud.notes.android.activity.EditNoteActivity.ACT
public abstract class BaseNoteFragment extends Fragment implements CategoryDialogFragment.CategoryDialogListener { public abstract class BaseNoteFragment extends Fragment implements CategoryDialogFragment.CategoryDialogListener {
public interface NoteFragmentListener { private static final String TAG = BaseNoteFragment.class.getSimpleName();
void close();
void onNoteUpdated(DBNote note);
}
private static final int MENU_ID_PIN = -1; private static final int MENU_ID_PIN = -1;
public static final String PARAM_NOTE_ID = "noteId"; public static final String PARAM_NOTE_ID = "noteId";
public static final String PARAM_ACCOUNT_ID = "accountId";
public static final String PARAM_NEWNOTE = "newNote"; public static final String PARAM_NEWNOTE = "newNote";
private static final String SAVEDKEY_NOTE = "note"; private static final String SAVEDKEY_NOTE = "note";
private static final String SAVEDKEY_ORIGINAL_NOTE = "original_note"; private static final String SAVEDKEY_ORIGINAL_NOTE = "original_note";
@ -58,6 +60,8 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
protected String searchQuery = null; protected String searchQuery = null;
private LocalAccount localAccount;
protected DBNote note; protected DBNote note;
@Nullable @Nullable
private DBNote originalNote; private DBNote originalNote;
@ -74,7 +78,6 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
if (savedInstanceState != null) { if (savedInstanceState != null) {
searchQuery = savedInstanceState.getString("searchQuery", ""); searchQuery = savedInstanceState.getString("searchQuery", "");
} }
} }
protected void setActiveTextView(TextView textView) { protected void setActiveTextView(TextView textView) {
@ -84,25 +87,43 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
isNew = true; try {
long id = getArguments().getLong(PARAM_NOTE_ID); this.localAccount = db.getLocalAccountByAccountName(SingleAccountHelper.getCurrentSingleSignOnAccount(getActivity().getApplicationContext()).name);
if (id > 0) {
note = originalNote = db.getNote(id); if (savedInstanceState == null) {
} else { isNew = true;
CloudNote cloudNote = (CloudNote) getArguments().getSerializable(PARAM_NEWNOTE); long id = getArguments().getLong(PARAM_NOTE_ID);
if (cloudNote == null) { if (id > 0) {
throw new IllegalArgumentException(PARAM_NOTE_ID + " is not given and argument " + PARAM_NEWNOTE + " is missing."); long accountId = getArguments().getLong(PARAM_ACCOUNT_ID);
if(accountId > 0) {
/* Switch account if account id has been provided */
this.localAccount = db.getAccount(accountId);
SingleAccountHelper.setCurrentAccount(getActivity().getApplicationContext(), localAccount.getAccountName());
try {
db.getNoteServerSyncHelper().updateAccount();
} catch(NextcloudFilesAppAccountNotFoundException e) {
e.printStackTrace();
}
}
note = originalNote = db.getNote(localAccount.getId(), id);
} else {
CloudNote cloudNote = (CloudNote) getArguments().getSerializable(PARAM_NEWNOTE);
if (cloudNote == null) {
throw new IllegalArgumentException(PARAM_NOTE_ID + " is not given and argument " + PARAM_NEWNOTE + " is missing.");
}
note = db.getNote(localAccount.getId(), db.addNoteAndSync(localAccount.getId(), cloudNote));
originalNote = null;
} }
note = db.getNote(db.addNoteAndSync(cloudNote)); } else {
originalNote = null; isNew = false;
note = (DBNote) savedInstanceState.getSerializable(SAVEDKEY_NOTE);
originalNote = (DBNote) savedInstanceState.getSerializable(SAVEDKEY_ORIGINAL_NOTE);
} }
} else { setHasOptionsMenu(true);
isNew = false; } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
note = (DBNote) savedInstanceState.getSerializable(SAVEDKEY_NOTE); e.printStackTrace();
originalNote = (DBNote) savedInstanceState.getSerializable(SAVEDKEY_ORIGINAL_NOTE);
} }
setHasOptionsMenu(true);
} }
@Override @Override
@ -234,7 +255,7 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
if (originalNote == null) { if (originalNote == null) {
db.deleteNoteAndSync(note.getId()); db.deleteNoteAndSync(note.getId());
} else { } else {
db.updateNoteAndSync(originalNote, null, null); db.updateNoteAndSync(localAccount.getId(), originalNote, null, null);
} }
listener.close(); listener.close();
return true; return true;
@ -310,22 +331,27 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
* @param callback Observer which is called after save/synchronization * @param callback Observer which is called after save/synchronization
*/ */
protected void saveNote(@Nullable ICallback callback) { protected void saveNote(@Nullable ICallback callback) {
Log.d(getClass().getSimpleName(), "saveData()"); Log.d(TAG, "saveData()");
String newContent = getContent(); if(note != null) {
if (note.getContent().equals(newContent)) { String newContent = getContent();
Log.v(getClass().getSimpleName(), "... not saving, since nothing has changed"); if (note.getContent().equals(newContent)) {
Log.v(TAG, "... not saving, since nothing has changed");
} else {
note = db.updateNoteAndSync(localAccount.getId(), note, newContent, callback);
listener.onNoteUpdated(note);
}
} else { } else {
note = db.updateNoteAndSync(note, newContent, callback); Log.e(TAG, "note is null");
listener.onNoteUpdated(note);
} }
} }
protected float getFontSizeFromPreferences(SharedPreferences sp) { protected float getFontSizeFromPreferences(SharedPreferences sp) {
final String prefValueSmall = getString(R.string.pref_value_font_size_small); final String prefValueSmall = getString(R.string.pref_value_font_size_small);
final String prefValueMedium = getString(R.string.pref_value_font_size_medium); final String prefValueMedium = getString(R.string.pref_value_font_size_medium);
final String prefValueLarge = getString(R.string.pref_value_font_size_large); // final String prefValueLarge = getString(R.string.pref_value_font_size_large);
String fontSize = sp.getString(getString(R.string.pref_key_font_size), prefValueMedium); String fontSize = sp.getString(getString(R.string.pref_key_font_size), prefValueMedium);
assert fontSize != null;
if (fontSize.equals(prefValueSmall)) { if (fontSize.equals(prefValueSmall)) {
return getResources().getDimension(R.dimen.note_font_size_small); return getResources().getDimension(R.dimen.note_font_size_small);
} else if (fontSize.equals(prefValueMedium)) { } else if (fontSize.equals(prefValueMedium)) {
@ -349,6 +375,7 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
} }
Bundle arguments = new Bundle(); Bundle arguments = new Bundle();
arguments.putString(CategoryDialogFragment.PARAM_CATEGORY, note.getCategory()); arguments.putString(CategoryDialogFragment.PARAM_CATEGORY, note.getCategory());
arguments.putLong(CategoryDialogFragment.PARAM_ACCOUNT_ID, note.getAccountId());
CategoryDialogFragment categoryFragment = new CategoryDialogFragment(); CategoryDialogFragment categoryFragment = new CategoryDialogFragment();
categoryFragment.setArguments(arguments); categoryFragment.setArguments(arguments);
categoryFragment.setTargetFragment(this, 0); categoryFragment.setTargetFragment(this, 0);
@ -360,4 +387,10 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
db.setCategory(note, category, null); db.setCategory(note, category, null);
listener.onNoteUpdated(note); listener.onNoteUpdated(note);
} }
public interface NoteFragmentListener {
void close();
void onNoteUpdated(DBNote note);
}
} }

View file

@ -5,7 +5,6 @@ import android.app.Dialog;
import android.app.DialogFragment; import android.app.DialogFragment;
import android.app.Fragment; import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
@ -14,10 +13,11 @@ import android.view.WindowManager;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Filter; import android.widget.Filter;
import androidx.annotation.NonNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import androidx.annotation.NonNull;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.R;
@ -32,6 +32,8 @@ import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
*/ */
public class CategoryDialogFragment extends DialogFragment { public class CategoryDialogFragment extends DialogFragment {
private static final String TAG = CategoryDialogFragment.class.getSimpleName();
/** /**
* Interface that must be implemented by the calling Activity. * Interface that must be implemented by the calling Activity.
*/ */
@ -44,10 +46,14 @@ public class CategoryDialogFragment extends DialogFragment {
void onCategoryChosen(String category); void onCategoryChosen(String category);
} }
public static final String PARAM_ACCOUNT_ID = "account_id";
public static final String PARAM_CATEGORY = "category"; public static final String PARAM_CATEGORY = "category";
private long accountId;
@BindView(R.id.editCategory) @BindView(R.id.editCategory)
AlwaysAutoCompleteTextView textCategory; AlwaysAutoCompleteTextView textCategory;
private FolderArrayAdapter adapter; private FolderArrayAdapter adapter;
@Override @Override
@ -56,6 +62,7 @@ public class CategoryDialogFragment extends DialogFragment {
ButterKnife.bind(this, dialogView); ButterKnife.bind(this, dialogView);
if (savedInstanceState == null) { if (savedInstanceState == null) {
textCategory.setText(getArguments().getString(PARAM_CATEGORY)); textCategory.setText(getArguments().getString(PARAM_CATEGORY));
accountId = getArguments().getLong(PARAM_ACCOUNT_ID);
} }
adapter = new FolderArrayAdapter(getActivity(), android.R.layout.simple_spinner_dropdown_item); adapter = new FolderArrayAdapter(getActivity(), android.R.layout.simple_spinner_dropdown_item);
textCategory.setAdapter(adapter); textCategory.setAdapter(adapter);
@ -64,24 +71,18 @@ public class CategoryDialogFragment extends DialogFragment {
.setTitle(R.string.change_category_title) .setTitle(R.string.change_category_title)
.setView(dialogView) .setView(dialogView)
.setCancelable(true) .setCancelable(true)
.setPositiveButton(R.string.action_edit_save, new DialogInterface.OnClickListener() { .setPositiveButton(R.string.action_edit_save, (dialog, which) -> {
@Override CategoryDialogListener listener;
public void onClick(DialogInterface dialog, int which) { Fragment target = getTargetFragment();
CategoryDialogListener listener; if (target instanceof CategoryDialogListener) {
Fragment target = getTargetFragment(); listener = (CategoryDialogListener) target;
if (target instanceof CategoryDialogListener) { } else {
listener = (CategoryDialogListener) target; listener = (CategoryDialogListener) getActivity();
} else {
listener = (CategoryDialogListener) getActivity();
}
listener.onCategoryChosen(textCategory.getText().toString());
} }
listener.onCategoryChosen(textCategory.getText().toString());
}) })
.setNegativeButton(R.string.simple_cancel, new DialogInterface.OnClickListener() { .setNegativeButton(R.string.simple_cancel, (dialog, which) -> {
@Override // do nothing
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
}) })
.create(); .create();
} }
@ -92,7 +93,7 @@ public class CategoryDialogFragment extends DialogFragment {
if (getDialog().getWindow() != null) { if (getDialog().getWindow() != null) {
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
} else { } else {
Log.w(CategoryDialogFragment.class.getSimpleName(), "can not set SOFT_INPUT_STATE_ALWAYAS_VISIBLE because getWindow() == null"); Log.w(TAG, "can not set SOFT_INPUT_STATE_ALWAYAS_VISIBLE because getWindow() == null");
} }
} }
@ -101,7 +102,7 @@ public class CategoryDialogFragment extends DialogFragment {
@Override @Override
protected List<String> doInBackground(Void... voids) { protected List<String> doInBackground(Void... voids) {
NoteSQLiteOpenHelper db = NoteSQLiteOpenHelper.getInstance(getActivity()); NoteSQLiteOpenHelper db = NoteSQLiteOpenHelper.getInstance(getActivity());
List<NavigationAdapter.NavigationItem> items = db.getCategories(); List<NavigationAdapter.NavigationItem> items = db.getCategories(accountId);
List<String> categories = new ArrayList<>(); List<String> categories = new ArrayList<>();
for (NavigationAdapter.NavigationItem item : items) { for (NavigationAdapter.NavigationItem item : items) {
if (!item.label.isEmpty()) { if (!item.label.isEmpty()) {

View file

@ -25,6 +25,8 @@ import com.yydcdut.markdown.syntax.edit.EditFactory;
import com.yydcdut.rxmarkdown.RxMDEditText; import com.yydcdut.rxmarkdown.RxMDEditText;
import com.yydcdut.rxmarkdown.RxMarkdown; import com.yydcdut.rxmarkdown.RxMarkdown;
import java.util.Objects;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.R;
@ -74,10 +76,11 @@ public class NoteEditFragment extends BaseNoteFragment {
} }
}; };
public static NoteEditFragment newInstance(long noteId) { public static NoteEditFragment newInstance(long accountId, long noteId) {
NoteEditFragment f = new NoteEditFragment(); NoteEditFragment f = new NoteEditFragment();
Bundle b = new Bundle(); Bundle b = new Bundle();
b.putLong(PARAM_NOTE_ID, noteId); b.putLong(PARAM_NOTE_ID, noteId);
b.putLong(PARAM_ACCOUNT_ID, accountId);
f.setArguments(b); f.setArguments(b);
return f; return f;
} }
@ -113,9 +116,9 @@ public class NoteEditFragment extends BaseNoteFragment {
public void onActivityCreated(@Nullable Bundle savedInstanceState) { public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
if(getView() != null) { ButterKnife.bind(this, Objects.requireNonNull(getView()));
ButterKnife.bind(this, getView());
if(note != null) {
setActiveTextView(editContent); setActiveTextView(editContent);
if (note.getContent().isEmpty()) { if (note.getContent().isEmpty()) {
@ -142,10 +145,12 @@ public class NoteEditFragment extends BaseNoteFragment {
.subscribe(new Subscriber<CharSequence>() { .subscribe(new Subscriber<CharSequence>() {
@Override @Override
public void onCompleted() { public void onCompleted() {
// Nothing to do here
} }
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
e.printStackTrace();
} }
@Override @Override
@ -160,8 +165,6 @@ public class NoteEditFragment extends BaseNoteFragment {
if (sp.getBoolean(getString(R.string.pref_key_font), false)) { if (sp.getBoolean(getString(R.string.pref_key_font), false)) {
editContent.setTypeface(Typeface.MONOSPACE); editContent.setTypeface(Typeface.MONOSPACE);
} }
} else {
Log.e(NoteEditFragment.class.getSimpleName(), "getView() is null");
} }
} }

View file

@ -14,12 +14,16 @@ import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.Nullable;
import com.yydcdut.markdown.syntax.text.TextFactory; import com.yydcdut.markdown.syntax.text.TextFactory;
import com.yydcdut.rxmarkdown.RxMDTextView; import com.yydcdut.rxmarkdown.RxMDTextView;
import com.yydcdut.rxmarkdown.RxMarkdown; import com.yydcdut.rxmarkdown.RxMarkdown;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import java.util.Objects;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.R;
@ -33,6 +37,8 @@ import rx.schedulers.Schedulers;
public class NotePreviewFragment extends BaseNoteFragment { public class NotePreviewFragment extends BaseNoteFragment {
private static final String TAG = NotePreviewFragment.class.getSimpleName();
private NoteSQLiteOpenHelper db = null; private NoteSQLiteOpenHelper db = null;
@BindView(R.id.swiperefreshlayout) @BindView(R.id.swiperefreshlayout)
@ -41,10 +47,11 @@ public class NotePreviewFragment extends BaseNoteFragment {
@BindView(R.id.single_note_content) @BindView(R.id.single_note_content)
RxMDTextView noteContent; RxMDTextView noteContent;
public static NotePreviewFragment newInstance(long noteId) { public static NotePreviewFragment newInstance(long accountId, long noteId) {
NotePreviewFragment f = new NotePreviewFragment(); NotePreviewFragment f = new NotePreviewFragment();
Bundle b = new Bundle(); Bundle b = new Bundle();
b.putLong(PARAM_NOTE_ID, noteId); b.putLong(PARAM_NOTE_ID, noteId);
b.putLong(PARAM_ACCOUNT_ID, accountId);
f.setArguments(b); f.setArguments(b);
return f; return f;
} }
@ -65,7 +72,7 @@ public class NotePreviewFragment extends BaseNoteFragment {
@Override @Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) { public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
ButterKnife.bind(this, getView()); ButterKnife.bind(this, Objects.requireNonNull(getView()));
setActiveTextView(noteContent); setActiveTextView(noteContent);
@ -99,7 +106,7 @@ public class NotePreviewFragment extends BaseNoteFragment {
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
Log.v(getClass().getSimpleName(), "RxMarkdown error", e); Log.v(TAG, "RxMarkdown error", e);
} }
@Override @Override

View file

@ -6,26 +6,21 @@ import android.preference.Preference;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
import android.preference.SwitchPreference; import android.preference.SwitchPreference;
import android.util.Log; import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import at.bitfire.cert4android.CustomCertManager;
import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.util.Notes; import it.niedermann.owncloud.notes.util.Notes;
public class PreferencesFragment extends PreferenceFragment { public class PreferencesFragment extends PreferenceFragment {
private static final String TAG = PreferencesFragment.class.getSimpleName();
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences); addPreferencesFromResource(R.xml.preferences);
Preference resetTrust = findPreference(getString(R.string.pref_key_reset_trust));
resetTrust.setOnPreferenceClickListener((Preference preference) -> {
CustomCertManager.Companion.resetCertificates(getActivity());
Toast.makeText(getActivity(), getString(R.string.settings_cert_reset_toast), Toast.LENGTH_SHORT).show();
return true;
});
final SwitchPreference themePref = (SwitchPreference) findPreference(getString(R.string.pref_key_theme)); final SwitchPreference themePref = (SwitchPreference) findPreference(getString(R.string.pref_key_theme));
themePref.setOnPreferenceChangeListener((Preference preference, Object newValue) -> { themePref.setOnPreferenceChangeListener((Preference preference, Object newValue) -> {
Boolean darkTheme = (Boolean) newValue; Boolean darkTheme = (Boolean) newValue;
@ -38,7 +33,7 @@ public class PreferencesFragment extends PreferenceFragment {
final SwitchPreference wifiOnlyPref = (SwitchPreference) findPreference(getString(R.string.pref_key_wifi_only)); final SwitchPreference wifiOnlyPref = (SwitchPreference) findPreference(getString(R.string.pref_key_wifi_only));
wifiOnlyPref.setOnPreferenceChangeListener((Preference preference, Object newValue) -> { wifiOnlyPref.setOnPreferenceChangeListener((Preference preference, Object newValue) -> {
Boolean syncOnWifiOnly = (Boolean) newValue; Boolean syncOnWifiOnly = (Boolean) newValue;
Log.v("Notes", "syncOnWifiOnly: " + syncOnWifiOnly); Log.v(TAG, "syncOnWifiOnly: " + syncOnWifiOnly);
return true; return true;
}); });
} }

View file

@ -1,11 +1,12 @@
package it.niedermann.owncloud.notes.model; package it.niedermann.owncloud.notes.model;
import androidx.annotation.NonNull;
import java.io.Serializable; import java.io.Serializable;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.Locale; import java.util.Locale;
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
import it.niedermann.owncloud.notes.util.NoteUtil; import it.niedermann.owncloud.notes.util.NoteUtil;
/** /**
@ -20,6 +21,7 @@ public class CloudNote implements Serializable {
private boolean favorite = false; private boolean favorite = false;
private String category = ""; private String category = "";
private String etag = ""; private String etag = "";
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
public CloudNote(long remoteId, Calendar modified, String title, String content, boolean favorite, String category, String etag) { public CloudNote(long remoteId, Calendar modified, String title, String content, boolean favorite, String category, String etag) {
this.remoteId = remoteId; this.remoteId = remoteId;
@ -96,9 +98,9 @@ public class CloudNote implements Serializable {
this.category = category == null ? "" : category; this.category = category == null ? "" : category;
} }
@NonNull
@Override @Override
public String toString() { public String toString() {
final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
return "R" + getRemoteId() + " " + (isFavorite() ? " (*) " : " ") + getCategory() + " / " + getTitle() + " (" + getModified(DATE_FORMAT) + " / " + getEtag() + ")"; return "R" + getRemoteId() + " " + (isFavorite() ? " (*) " : " ") + getCategory() + " / " + getTitle() + " (" + getModified(DATE_FORMAT) + " / " + getEtag() + ")";
} }
} }

View file

@ -1,10 +1,10 @@
package it.niedermann.owncloud.notes.model; package it.niedermann.owncloud.notes.model;
import androidx.annotation.NonNull;
import java.io.Serializable; import java.io.Serializable;
import java.util.Calendar; import java.util.Calendar;
import it.niedermann.owncloud.notes.util.NoteUtil;
/** /**
* DBNote represents a single note from the local SQLite database with all attributes. * DBNote represents a single note from the local SQLite database with all attributes.
* It extends CloudNote with attributes required for local data management. * It extends CloudNote with attributes required for local data management.
@ -12,20 +12,26 @@ import it.niedermann.owncloud.notes.util.NoteUtil;
public class DBNote extends CloudNote implements Item, Serializable { public class DBNote extends CloudNote implements Item, Serializable {
private long id; private long id;
private long accountId;
private DBStatus status; private DBStatus status;
private String excerpt = ""; private String excerpt;
public DBNote(long id, long remoteId, Calendar modified, String title, String content, boolean favorite, String category, String etag, DBStatus status) { public DBNote(long id, long remoteId, Calendar modified, String title, String content, boolean favorite, String category, String etag, DBStatus status, long accountId, String excerpt) {
super(remoteId, modified, title, content, favorite, category, etag); super(remoteId, modified, title, content, favorite, category, etag);
this.id = id; this.id = id;
setExcerpt(content); this.excerpt = excerpt;
this.status = status; this.status = status;
this.accountId = accountId;
} }
public long getId() { public long getId() {
return id; return id;
} }
public long getAccountId() {
return accountId;
}
public DBStatus getStatus() { public DBStatus getStatus() {
return status; return status;
} }
@ -38,17 +44,12 @@ public class DBNote extends CloudNote implements Item, Serializable {
return excerpt; return excerpt;
} }
public void setExcerptDirectly(String content) { public void setExcerpt(String excerpt) {
excerpt = content; this.excerpt = excerpt;
}
private void setExcerpt(String content) {
excerpt = NoteUtil.generateNoteExcerpt(content);
} }
public void setContent(String content) { public void setContent(String content) {
super.setContent(content); super.setContent(content);
setExcerpt(content);
} }
@Override @Override
@ -56,8 +57,14 @@ public class DBNote extends CloudNote implements Item, Serializable {
return false; return false;
} }
@NonNull
@Override @Override
public String toString() { public String toString() {
return "#" + getId() + "/" + super.toString() + " " + getStatus(); return "DBNote{" +
"id=" + id +
", accountId=" + accountId +
", status=" + status +
", excerpt='" + excerpt + '\'' +
'}';
} }
} }

View file

@ -1,7 +1,5 @@
package it.niedermann.owncloud.notes.model; package it.niedermann.owncloud.notes.model;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.text.Html; import android.text.Html;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -9,6 +7,9 @@ import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -23,9 +24,9 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int section_type = 0; private static final int section_type = 0;
private static final int note_type = 1; private static final int note_type = 1;
private final NoteClickListener noteClickListener; private final NoteClickListener noteClickListener;
private List<Item> itemList = null; private List<Item> itemList;
private boolean showCategory = true; private boolean showCategory = true;
private List<Integer> selected = null; private List<Integer> selected;
public ItemAdapter(@NonNull NoteClickListener noteClickListener) { public ItemAdapter(@NonNull NoteClickListener noteClickListener) {
this.itemList = new ArrayList<>(); this.itemList = new ArrayList<>();
@ -54,17 +55,6 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
notifyItemChanged(0); notifyItemChanged(0);
} }
/**
* Replaces a note with an updated version
*
* @param note Note with the changes.
* @param position position in the list of the node
*/
public void replace(@NonNull DBNote note, int position) {
itemList.set(position, note);
notifyItemChanged(position);
}
/** /**
* Removes all items from the adapter. * Removes all items from the adapter.
*/ */
@ -74,8 +64,9 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
} }
// Create new views (invoked by the layout manager) // Create new views (invoked by the layout manager)
@NonNull
@Override @Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v; View v;
if (viewType == section_type) { if (viewType == section_type) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_notes_list_section_item, parent, false); v = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_notes_list_section_item, parent, false);
@ -89,7 +80,7 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
// Replace the contents of a view (invoked by the layout manager) // Replace the contents of a view (invoked by the layout manager)
@Override @Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
// - get element from your dataset at this position // - get element from your dataset at this position
// - replace the contents of the view with that element // - replace the contents of the view with that element
Item item = itemList.get(position); Item item = itemList.get(position);
@ -106,12 +97,7 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
nvHolder.noteExcerpt.setText(Html.fromHtml(note.getExcerpt())); nvHolder.noteExcerpt.setText(Html.fromHtml(note.getExcerpt()));
nvHolder.noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? View.INVISIBLE : View.VISIBLE); nvHolder.noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? View.INVISIBLE : View.VISIBLE);
nvHolder.noteFavorite.setImageResource(note.isFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp); nvHolder.noteFavorite.setImageResource(note.isFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp);
nvHolder.noteFavorite.setOnClickListener(new View.OnClickListener() { nvHolder.noteFavorite.setOnClickListener(view -> noteClickListener.onNoteFavoriteClick(holder.getAdapterPosition(), view));
@Override
public void onClick(View view) {
noteClickListener.onNoteFavoriteClick(holder.getAdapterPosition(), view);
}
});
} }
} }
@ -128,16 +114,15 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
return selected; return selected;
} }
public boolean deselect(Integer position) { public void deselect(Integer position) {
for (int i = 0; i < selected.size(); i++) { for (int i = 0; i < selected.size(); i++) {
if (selected.get(i).equals(position)) { if (selected.get(i).equals(position)) {
//position was selected and removed //position was selected and removed
selected.remove(i); selected.remove(i);
return true; return;
} }
} }
// position was not selected // position was not selected
return false;
} }
public Item getItem(int notePosition) { public Item getItem(int notePosition) {
@ -175,7 +160,8 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@BindView(R.id.noteSwipeable) @BindView(R.id.noteSwipeable)
public View noteSwipeable; public View noteSwipeable;
View noteSwipeFrame; View noteSwipeFrame;
ImageView noteFavoriteLeft, noteDeleteRight; ImageView noteFavoriteLeft;
ImageView noteDeleteRight;
TextView noteTitle; TextView noteTitle;
@BindView(R.id.noteCategory) @BindView(R.id.noteCategory)
TextView noteCategory; TextView noteCategory;

View file

@ -0,0 +1,74 @@
package it.niedermann.owncloud.notes.model;
import androidx.annotation.NonNull;
public class LocalAccount {
private long id;
private String userName;
private String accountName;
private String url;
private String etag;
private long modified;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getEtag() {
return etag;
}
public void setETag(String etag) {
this.etag = etag;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public long getModified() {
return modified;
}
public void setModified(long modified) {
this.modified = modified;
}
@NonNull
@Override
public String toString() {
return "LocalAccount{" +
"id=" + id +
", userName='" + userName + '\'' +
", accountName='" + accountName + '\'' +
", url='" + url + '\'' +
", etag='" + etag + '\'' +
", modified='" + modified + '\'' +
'}';
}
}

View file

@ -0,0 +1,19 @@
package it.niedermann.owncloud.notes.model;
import androidx.annotation.StringRes;
import it.niedermann.owncloud.notes.R;
public enum LoginStatus {
OK(0),
NO_NETWORK(R.string.error_no_network),
JSON_FAILED(R.string.error_json),
PROBLEM_WITH_FILES_APP(R.string.error_files_app);
@StringRes
public final int str;
LoginStatus(@StringRes int str) {
this.str = str;
}
}

View file

@ -1,16 +1,18 @@
package it.niedermann.owncloud.notes.model; package it.niedermann.owncloud.notes.model;
import android.graphics.Color; import android.graphics.Color;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -71,18 +73,8 @@ public class NavigationAdapter extends RecyclerView.Adapter<NavigationAdapter.Vi
super(itemView); super(itemView);
view = itemView; view = itemView;
ButterKnife.bind(this, view); ButterKnife.bind(this, view);
icon.setOnClickListener(new View.OnClickListener() { icon.setOnClickListener(view -> clickListener.onIconClick(currentItem));
@Override itemView.setOnClickListener(view -> clickListener.onItemClick(currentItem));
public void onClick(View view) {
clickListener.onIconClick(currentItem);
}
});
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
clickListener.onItemClick(currentItem);
}
});
} }
void assignItem(@NonNull NavigationItem item) { void assignItem(@NonNull NavigationItem item) {
@ -92,7 +84,7 @@ public class NavigationAdapter extends RecyclerView.Adapter<NavigationAdapter.Vi
count.setVisibility(item.count == null ? View.GONE : View.VISIBLE); count.setVisibility(item.count == null ? View.GONE : View.VISIBLE);
count.setText(String.valueOf(item.count)); count.setText(String.valueOf(item.count));
if (item.icon > 0) { if (item.icon > 0) {
icon.setImageDrawable(icon.getResources().getDrawable(item.icon)); icon.setImageDrawable(DrawableCompat.wrap(icon.getResources().getDrawable(item.icon)));
icon.setVisibility(View.VISIBLE); icon.setVisibility(View.VISIBLE);
} else { } else {
icon.setVisibility(View.GONE); icon.setVisibility(View.GONE);
@ -108,7 +100,6 @@ public class NavigationAdapter extends RecyclerView.Adapter<NavigationAdapter.Vi
public interface ClickListener { public interface ClickListener {
void onItemClick(NavigationItem item); void onItemClick(NavigationItem item);
void onIconClick(NavigationItem item); void onIconClick(NavigationItem item);
} }

View file

@ -2,14 +2,16 @@ package it.niedermann.owncloud.notes.persistence;
import android.content.Context; import android.content.Context;
import android.os.AsyncTask; import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import android.text.Html; import android.text.Html;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
@ -29,18 +31,21 @@ public class LoadNotesListTask extends AsyncTask<Void, Void, List<Item>> {
private final NotesLoadedListener callback; private final NotesLoadedListener callback;
private final Category category; private final Category category;
private final CharSequence searchQuery; private final CharSequence searchQuery;
public LoadNotesListTask(@NonNull Context context, @NonNull NotesLoadedListener callback, @NonNull Category category, @Nullable CharSequence searchQuery) { private final long accountId;
public LoadNotesListTask(long accountId, @NonNull Context context, @NonNull NotesLoadedListener callback, @NonNull Category category, @Nullable CharSequence searchQuery) {
this.context = context; this.context = context;
this.callback = callback; this.callback = callback;
this.category = category; this.category = category;
this.searchQuery = searchQuery; this.searchQuery = searchQuery;
this.accountId = accountId;
} }
@Override @Override
protected List<Item> doInBackground(Void... voids) { protected List<Item> doInBackground(Void... voids) {
List<DBNote> noteList; List<DBNote> noteList;
NoteSQLiteOpenHelper db = NoteSQLiteOpenHelper.getInstance(context); NoteSQLiteOpenHelper db = NoteSQLiteOpenHelper.getInstance(context);
noteList = db.searchNotes(searchQuery, category.category, category.favorite); noteList = db.searchNotes(accountId, searchQuery, category.category, category.favorite);
if (category.category == null) { if (category.category == null) {
return fillListByTime(noteList); return fillListByTime(noteList);
@ -67,7 +72,7 @@ public class LoadNotesListTask extends AsyncTask<Void, Void, List<Item>> {
matcher.start(), matcher.end(), 0); matcher.start(), matcher.end(), 0);
} }
dbNote.setExcerptDirectly(Html.toHtml(spannableString)); dbNote.setExcerpt(Html.toHtml(spannableString));
} }
return dbNote; return dbNote;
@ -93,68 +98,16 @@ public class LoadNotesListTask extends AsyncTask<Void, Void, List<Item>> {
@WorkerThread @WorkerThread
private List<Item> fillListByTime(@NonNull List<DBNote> noteList) { private List<Item> fillListByTime(@NonNull List<DBNote> noteList) {
List<Item> itemList = new ArrayList<>(); List<Item> itemList = new ArrayList<>();
// #12 Create Sections depending on Time Timeslotter timeslotter = new Timeslotter();
boolean todaySet, yesterdaySet, weekSet, monthSet, earlierSet; String lastTimeslot = null;
todaySet = yesterdaySet = weekSet = monthSet = earlierSet = false;
Calendar today = Calendar.getInstance();
today.set(Calendar.HOUR_OF_DAY, 0);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);
today.set(Calendar.MILLISECOND, 0);
Calendar yesterday = Calendar.getInstance();
yesterday.set(Calendar.DAY_OF_YEAR, yesterday.get(Calendar.DAY_OF_YEAR) - 1);
yesterday.set(Calendar.HOUR_OF_DAY, 0);
yesterday.set(Calendar.MINUTE, 0);
yesterday.set(Calendar.SECOND, 0);
yesterday.set(Calendar.MILLISECOND, 0);
Calendar week = Calendar.getInstance();
week.set(Calendar.DAY_OF_WEEK, week.getFirstDayOfWeek());
week.set(Calendar.HOUR_OF_DAY, 0);
week.set(Calendar.MINUTE, 0);
week.set(Calendar.SECOND, 0);
week.set(Calendar.MILLISECOND, 0);
Calendar month = Calendar.getInstance();
month.set(Calendar.DAY_OF_MONTH, 0);
month.set(Calendar.HOUR_OF_DAY, 0);
month.set(Calendar.MINUTE, 0);
month.set(Calendar.SECOND, 0);
month.set(Calendar.MILLISECOND, 0);
for (int i = 0; i < noteList.size(); i++) { for (int i = 0; i < noteList.size(); i++) {
DBNote currentNote = noteList.get(i); DBNote currentNote = noteList.get(i);
if (currentNote.isFavorite()) { String timeslot = timeslotter.getTimeslot(currentNote);
// don't show as new section if(i > 0 && !timeslot.equals(lastTimeslot)) {
} else if (!todaySet && currentNote.getModified().getTimeInMillis() >= today.getTimeInMillis()) { itemList.add(new SectionItem(timeslot));
// after 00:00 today
if (i > 0) {
itemList.add(new SectionItem(context.getResources().getString(R.string.listview_updated_today)));
}
todaySet = true;
} else if (!yesterdaySet && currentNote.getModified().getTimeInMillis() < today.getTimeInMillis() && currentNote.getModified().getTimeInMillis() >= yesterday.getTimeInMillis()) {
// between today 00:00 and yesterday 00:00
if (i > 0) {
itemList.add(new SectionItem(context.getResources().getString(R.string.listview_updated_yesterday)));
}
yesterdaySet = true;
} else if (!weekSet && currentNote.getModified().getTimeInMillis() < yesterday.getTimeInMillis() && currentNote.getModified().getTimeInMillis() >= week.getTimeInMillis()) {
// between yesterday 00:00 and start of the week 00:00
if (i > 0) {
itemList.add(new SectionItem(context.getResources().getString(R.string.listview_updated_this_week)));
}
weekSet = true;
} else if (!monthSet && currentNote.getModified().getTimeInMillis() < week.getTimeInMillis() && currentNote.getModified().getTimeInMillis() >= month.getTimeInMillis()) {
// between start of the week 00:00 and start of the month 00:00
if (i > 0) {
itemList.add(new SectionItem(context.getResources().getString(R.string.listview_updated_this_month)));
}
monthSet = true;
} else if (!earlierSet && currentNote.getModified().getTimeInMillis() < month.getTimeInMillis()) {
// before start of the month 00:00
if (i > 0) {
itemList.add(new SectionItem(context.getResources().getString(R.string.listview_updated_earlier)));
}
earlierSet = true;
} }
itemList.add(colorTheNote(currentNote)); itemList.add(colorTheNote(currentNote));
lastTimeslot = timeslot;
} }
return itemList; return itemList;
@ -168,4 +121,53 @@ public class LoadNotesListTask extends AsyncTask<Void, Void, List<Item>> {
public interface NotesLoadedListener { public interface NotesLoadedListener {
void onNotesLoaded(List<Item> notes, boolean showCategory); void onNotesLoaded(List<Item> notes, boolean showCategory);
} }
private class Timeslotter {
private final List<Timeslot> timeslots = new ArrayList<>();
private final Calendar lastYear;
Timeslotter() {
Calendar now = Calendar.getInstance();
int month = now.get(Calendar.MONTH);
int day = now.get(Calendar.DAY_OF_MONTH);
int offsetWeekStart = (now.get(Calendar.DAY_OF_WEEK) - now.getFirstDayOfWeek() + 7) % 7;
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_today), month, day));
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_yesterday), month,day - 1));
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_this_week), month,day - offsetWeekStart));
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_last_week), month,day - offsetWeekStart - 7));
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_this_month), month,1));
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_last_month), month - 1, 1));
lastYear = Calendar.getInstance();
lastYear.set(now.get(Calendar.YEAR) - 1, 0, 1, 0, 0, 0);
}
String getTimeslot(DBNote note) {
if (note.isFavorite()) {
return "";
}
Calendar modified = note.getModified();
for (Timeslot timeslot : timeslots) {
if (!modified.before(timeslot.time)) {
return timeslot.label;
}
}
if (!modified.before(this.lastYear)) {
// use YEAR and MONTH in a format based on current locale
return DateUtils.formatDateTime(context, modified.getTimeInMillis(), DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_NO_MONTH_DAY);
} else {
return Integer.toString(modified.get(Calendar.YEAR));
}
}
private class Timeslot {
final String label;
final Calendar time;
Timeslot(String label, int month, int day) {
this.label = label;
this.time = Calendar.getInstance();
this.time.set(this.time.get(Calendar.YEAR), month, day, 0, 0, 0);
}
}
}
} }

View file

@ -1,13 +1,20 @@
package it.niedermann.owncloud.notes.persistence; package it.niedermann.owncloud.notes.persistence;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ShortcutManager; import android.content.pm.ShortcutManager;
import android.content.res.Resources;
import android.database.Cursor; import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build; import android.os.Build;
import android.preference.PreferenceManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@ -15,6 +22,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread; import androidx.annotation.WorkerThread;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections; import java.util.Collections;
@ -28,7 +37,9 @@ import it.niedermann.owncloud.notes.android.appwidget.SingleNoteWidget;
import it.niedermann.owncloud.notes.model.CloudNote; import it.niedermann.owncloud.notes.model.CloudNote;
import it.niedermann.owncloud.notes.model.DBNote; import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.model.DBStatus; import it.niedermann.owncloud.notes.model.DBStatus;
import it.niedermann.owncloud.notes.model.LocalAccount;
import it.niedermann.owncloud.notes.model.NavigationAdapter; import it.niedermann.owncloud.notes.model.NavigationAdapter;
import it.niedermann.owncloud.notes.util.DatabaseIndexUtil;
import it.niedermann.owncloud.notes.util.ICallback; import it.niedermann.owncloud.notes.util.ICallback;
import it.niedermann.owncloud.notes.util.NoteUtil; import it.niedermann.owncloud.notes.util.NoteUtil;
@ -37,19 +48,33 @@ import it.niedermann.owncloud.notes.util.NoteUtil;
*/ */
public class NoteSQLiteOpenHelper extends SQLiteOpenHelper { public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
private static final int database_version = 8; private static final String TAG = NoteSQLiteOpenHelper.class.getSimpleName();
private static final int database_version = 10;
private static final String database_name = "OWNCLOUD_NOTES"; private static final String database_name = "OWNCLOUD_NOTES";
private static final String table_notes = "NOTES"; private static final String table_notes = "NOTES";
private static final String table_accounts = "ACCOUNTS";
private static final String key_id = "ID"; private static final String key_id = "ID";
private static final String key_url = "URL";
private static final String key_account_name = "ACCOUNT_NAME";
private static final String key_username = "USERNAME";
private static final String key_account_id = "ACCOUNT_ID";
private static final String key_remote_id = "REMOTEID"; private static final String key_remote_id = "REMOTEID";
private static final String key_status = "STATUS"; private static final String key_status = "STATUS";
private static final String key_title = "TITLE"; private static final String key_title = "TITLE";
private static final String key_modified = "MODIFIED"; private static final String key_modified = "MODIFIED";
private static final String key_content = "CONTENT"; private static final String key_content = "CONTENT";
private static final String key_excerpt = "EXCERPT";
private static final String key_favorite = "FAVORITE"; private static final String key_favorite = "FAVORITE";
private static final String key_category = "CATEGORY"; private static final String key_category = "CATEGORY";
private static final String key_etag = "ETAG"; private static final String key_etag = "ETAG";
private static final String[] columns = {key_id, key_remote_id, key_status, key_title, key_modified, key_content, key_favorite, key_category, key_etag};
private static final String[] columnsWithoutContent = {key_id, key_remote_id, key_status, key_title, key_modified, key_favorite, key_category, key_etag, key_excerpt};
private static final String[] columns = {key_id, key_remote_id, key_status, key_title, key_modified, key_favorite, key_category, key_etag, key_excerpt, key_content};
private static final String default_order = key_favorite + " DESC, " + key_modified + " DESC"; private static final String default_order = key_favorite + " DESC, " + key_modified + " DESC";
private static NoteSQLiteOpenHelper instance; private static NoteSQLiteOpenHelper instance;
@ -59,13 +84,13 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
private NoteSQLiteOpenHelper(Context context) { private NoteSQLiteOpenHelper(Context context) {
super(context, database_name, null, database_version); super(context, database_name, null, database_version);
this.context = context.getApplicationContext(); this.context = context;
serverSyncHelper = NoteServerSyncHelper.getInstance(this); serverSyncHelper = NoteServerSyncHelper.getInstance(this);
} }
public static NoteSQLiteOpenHelper getInstance(Context context) { public static NoteSQLiteOpenHelper getInstance(Context context) {
if (instance == null) if (instance == null)
return instance = new NoteSQLiteOpenHelper(context.getApplicationContext()); return instance = new NoteSQLiteOpenHelper(context);
else else
return instance; return instance;
} }
@ -81,23 +106,37 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
*/ */
@Override @Override
public void onCreate(SQLiteDatabase db) { public void onCreate(SQLiteDatabase db) {
createTable(db, table_notes); createAccountTable(db, table_accounts);
createNotesTable(db, table_notes);
} }
private void createTable(SQLiteDatabase db, String tableName) { private void createNotesTable(@NonNull SQLiteDatabase db, @NonNull String tableName) {
db.execSQL("CREATE TABLE " + tableName + " ( " + db.execSQL("CREATE TABLE " + tableName + " ( " +
key_id + " INTEGER PRIMARY KEY AUTOINCREMENT, " + key_id + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
key_remote_id + " INTEGER, " + key_remote_id + " INTEGER, " +
key_account_id + " INTEGER, " +
key_status + " VARCHAR(50), " + key_status + " VARCHAR(50), " +
key_title + " TEXT, " + key_title + " TEXT, " +
key_modified + " INTEGER DEFAULT 0, " + key_modified + " INTEGER DEFAULT 0, " +
key_content + " TEXT, " + key_content + " TEXT, " +
key_favorite + " INTEGER DEFAULT 0, " + key_favorite + " INTEGER DEFAULT 0, " +
key_category + " TEXT NOT NULL DEFAULT '', " + key_category + " TEXT NOT NULL DEFAULT '', " +
key_etag + " TEXT)"); key_etag + " TEXT," +
createIndexes(db); key_excerpt + " TEXT NOT NULL DEFAULT '', " +
"FOREIGN KEY(" + key_account_id + ") REFERENCES " + table_accounts + "(" + key_id + "))");
createNotesIndexes(db);
} }
private void createAccountTable(@NonNull SQLiteDatabase db, @NonNull String tableName) {
db.execSQL("CREATE TABLE " + tableName + " ( " +
key_id + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
key_url + " TEXT, " +
key_username + " TEXT, " +
key_account_name + " TEXT UNIQUE, " +
key_etag + " TEXT, " +
key_modified + " INTEGER)");
createAccountIndexes(db);
}
@Override @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
@ -105,7 +144,8 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
recreateDatabase(db); recreateDatabase(db);
} }
if (oldVersion < 4) { if (oldVersion < 4) {
clearDatabase(db); db.delete(table_notes, null, null);
db.delete(table_accounts, null, null);
} }
if (oldVersion < 5) { if (oldVersion < 5) {
db.execSQL("ALTER TABLE " + table_notes + " ADD COLUMN " + key_remote_id + " INTEGER"); db.execSQL("ALTER TABLE " + table_notes + " ADD COLUMN " + key_remote_id + " INTEGER");
@ -116,19 +156,117 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
db.execSQL("ALTER TABLE " + table_notes + " ADD COLUMN " + key_favorite + " INTEGER DEFAULT 0"); db.execSQL("ALTER TABLE " + table_notes + " ADD COLUMN " + key_favorite + " INTEGER DEFAULT 0");
} }
if (oldVersion < 7) { if (oldVersion < 7) {
dropIndexes(db); DatabaseIndexUtil.dropIndexes(db);
db.execSQL("ALTER TABLE " + table_notes + " ADD COLUMN " + key_category + " TEXT NOT NULL DEFAULT ''"); db.execSQL("ALTER TABLE " + table_notes + " ADD COLUMN " + key_category + " TEXT NOT NULL DEFAULT ''");
db.execSQL("ALTER TABLE " + table_notes + " ADD COLUMN " + key_etag + " TEXT"); db.execSQL("ALTER TABLE " + table_notes + " ADD COLUMN " + key_etag + " TEXT");
createIndexes(db); createNotesIndexes(db);
} }
if (oldVersion < 8) { if (oldVersion < 8) {
final String table_temp = "NOTES_TEMP"; final String table_temp = "NOTES_TEMP";
createTable(db, table_temp); createNotesTable(db, table_temp);
db.execSQL(String.format("INSERT INTO %s(%s,%s,%s,%s,%s,%s,%s,%s,%s) ", table_temp, key_id, key_remote_id, key_status, key_title, key_modified, key_content, key_favorite, key_category, key_etag) db.execSQL(String.format("INSERT INTO %s(%s,%s,%s,%s,%s,%s,%s,%s,%s) ", table_temp, key_id, key_remote_id, key_status, key_title, key_modified, key_content, key_favorite, key_category, key_etag)
+ String.format("SELECT %s,%s,%s,%s,strftime('%%s',%s),%s,%s,%s,%s FROM %s", key_id, key_remote_id, key_status, key_title, key_modified, key_content, key_favorite, key_category, key_etag, table_notes)); + String.format("SELECT %s,%s,%s,%s,strftime('%%s',%s),%s,%s,%s,%s FROM %s", key_id, key_remote_id, key_status, key_title, key_modified, key_content, key_favorite, key_category, key_etag, table_notes));
db.execSQL(String.format("DROP TABLE %s", table_notes)); db.execSQL(String.format("DROP TABLE %s", table_notes));
db.execSQL(String.format("ALTER TABLE %s RENAME TO %s", table_temp, table_notes)); db.execSQL(String.format("ALTER TABLE %s RENAME TO %s", table_temp, table_notes));
} }
if (oldVersion < 9) {
// Create accounts table
createAccountTable(db, table_accounts);
// Add accountId to notes table
db.execSQL("ALTER TABLE " + table_notes + " ADD COLUMN " + key_account_id + " INTEGER NOT NULL DEFAULT 0");
DatabaseIndexUtil.createIndex(db, table_notes, key_account_id);
// Migrate existing account from SharedPreferences
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
String username = sharedPreferences.getString("settingsUsername", "");
String url = sharedPreferences.getString("settingsUrl", "");
if (url != null && url.endsWith("/")) {
url = url.substring(0, url.length() - 1);
try {
String accountName = username + "@" + new URL(url).getHost();
ContentValues migratedAccountValues = new ContentValues();
migratedAccountValues.put(key_url, url);
migratedAccountValues.put(key_username, username);
migratedAccountValues.put(key_account_name, accountName);
db.insert(table_accounts, null, migratedAccountValues);
// After successful insertion of migrated account, set accountId to 1 in each note
ContentValues values = new ContentValues();
values.put(key_account_id, 1);
db.update(table_notes, values, key_account_id + " = ?", new String[]{"NULL"});
// Add FOREIGN_KEY constraint
final String table_temp = "NOTES_TEMP";
db.execSQL(String.format("ALTER TABLE %s RENAME TO %s", table_notes, table_temp));
db.execSQL("CREATE TABLE " + table_notes + " ( " +
key_id + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
key_remote_id + " INTEGER, " +
key_account_id + " INTEGER, " +
key_status + " VARCHAR(50), " +
key_title + " TEXT, " +
key_modified + " INTEGER DEFAULT 0, " +
key_content + " TEXT, " +
key_favorite + " INTEGER DEFAULT 0, " +
key_category + " TEXT NOT NULL DEFAULT '', " +
key_etag + " TEXT," +
"FOREIGN KEY(" + key_account_id + ") REFERENCES " + table_accounts + "(" + key_id + "))");
DatabaseIndexUtil.createIndex(db, table_notes, key_remote_id, key_account_id, key_status, key_favorite, key_category, key_modified);
db.execSQL(String.format("INSERT INTO %s(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) ", table_notes, key_id, key_account_id, key_remote_id, key_status, key_title, key_modified, key_content, key_favorite, key_category, key_etag)
+ String.format("SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s", key_id, values.get(key_account_id), key_remote_id, key_status, key_title, key_modified, key_content, key_favorite, key_category, key_etag, table_temp));
db.execSQL(String.format("DROP TABLE %s;", table_temp));
AppWidgetManager awm = AppWidgetManager.getInstance(context);
SharedPreferences.Editor editor = sharedPreferences.edit();
// Add accountId '1' to any existing (and configured) appwidgets
int[] appWidgetIdsNLW = awm.getAppWidgetIds(new ComponentName(context, NoteListWidget.class));
int[] appWidgetIdsSNW = awm.getAppWidgetIds(new ComponentName(context, SingleNoteWidget.class));
for (int appWidgetId : appWidgetIdsNLW) {
if (sharedPreferences.getInt(NoteListWidget.WIDGET_MODE_KEY + appWidgetId, -1) >= 0) {
editor.putLong(NoteListWidget.ACCOUNT_ID_KEY + appWidgetId, 1);
}
}
for (int appWidgetId : appWidgetIdsSNW) {
if (sharedPreferences.getLong(SingleNoteWidget.WIDGET_KEY + appWidgetId, -1) >= 0) {
editor.putLong(SingleNoteWidget.ACCOUNT_ID_KEY + appWidgetId, 1);
}
}
notifyNotesChanged();
// Clean up no longer needed SharedPreferences
editor.remove("notes_last_etag");
editor.remove("notes_last_modified");
editor.remove("settingsUrl");
editor.remove("settingsUsername");
editor.remove("settingsPassword");
editor.apply();
} catch (MalformedURLException e) {
Log.e(TAG, "Previous URL could not be parsed. Recreating database...");
e.printStackTrace();
recreateDatabase(db);
}
} else {
Log.e(TAG, "Previous URL is null. Recreating database...");
recreateDatabase(db);
}
}
if (oldVersion < 10) {
db.execSQL("ALTER TABLE " + table_notes + " ADD COLUMN " + key_excerpt + " INTEGER NOT NULL DEFAULT ''");
Cursor cursor = db.query(table_notes, new String[]{key_id, key_content}, null, null, null, null, null, null);
while (cursor.moveToNext()) {
ContentValues values = new ContentValues();
values.put(key_excerpt, NoteUtil.generateNoteExcerpt(cursor.getString(1)));
db.update(table_notes, values, key_id + " = ? ", new String[]{cursor.getString(0)});
}
cursor.close();
}
} }
@Override @Override
@ -136,61 +274,33 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
recreateDatabase(db); recreateDatabase(db);
} }
private void clearDatabase(SQLiteDatabase db) {
db.delete(table_notes, null, null);
}
private void recreateDatabase(SQLiteDatabase db) { private void recreateDatabase(SQLiteDatabase db) {
dropIndexes(db); DatabaseIndexUtil.dropIndexes(db);
db.execSQL("DROP TABLE " + table_notes); db.execSQL("DROP TABLE IF EXISTS " + table_notes);
db.execSQL("DROP TABLE IF EXISTS " + table_accounts);
onCreate(db); onCreate(db);
} }
private void dropIndexes(SQLiteDatabase db) { private static void createNotesIndexes(@NonNull SQLiteDatabase db) {
Cursor c = db.query("sqlite_master", new String[]{"name"}, "type=?", new String[]{"index"}, null, null, null); DatabaseIndexUtil.createIndex(db, table_notes, key_remote_id, key_account_id, key_status, key_favorite, key_category, key_modified);
while (c.moveToNext()) {
db.execSQL("DROP INDEX " + c.getString(0));
}
c.close();
} }
private void createIndexes(SQLiteDatabase db) { private static void createAccountIndexes(@NonNull SQLiteDatabase db) {
createIndex(db, table_notes, key_remote_id); DatabaseIndexUtil.createIndex(db, table_accounts, key_url, key_username, key_account_name, key_etag, key_modified);
createIndex(db, table_notes, key_status);
createIndex(db, table_notes, key_favorite);
createIndex(db, table_notes, key_category);
createIndex(db, table_notes, key_modified);
}
private void createIndex(SQLiteDatabase db, String table, String column) {
String indexName = table + "_" + column + "_idx";
db.execSQL("CREATE INDEX IF NOT EXISTS " + indexName + " ON " + table + "(" + column + ")");
} }
public Context getContext() { public Context getContext() {
return context; return context;
} }
/**
* Creates a new Note in the Database and adds a Synchronization Flag.
*
* @param content String
*/
@SuppressWarnings("UnusedReturnValue")
public long addNoteAndSync(String content, String category, boolean favorite) {
CloudNote note = new CloudNote(0, Calendar.getInstance(), NoteUtil.generateNonEmptyNoteTitle(content, getContext()), content, favorite, category, null);
return addNoteAndSync(note);
}
/** /**
* Creates a new Note in the Database and adds a Synchronization Flag. * Creates a new Note in the Database and adds a Synchronization Flag.
* *
* @param note Note * @param note Note
*/ */
@SuppressWarnings("UnusedReturnValue") public long addNoteAndSync(long accountId, CloudNote note) {
public long addNoteAndSync(CloudNote note) { DBNote dbNote = new DBNote(0, 0, note.getModified(), note.getTitle(), note.getContent(), note.isFavorite(), note.getCategory(), note.getEtag(), DBStatus.LOCAL_EDITED, accountId, NoteUtil.generateNoteExcerpt(note.getContent()));
DBNote dbNote = new DBNote(0, 0, note.getModified(), note.getTitle(), note.getContent(), note.isFavorite(), note.getCategory(), note.getEtag(), DBStatus.LOCAL_EDITED); long id = addNote(accountId, dbNote);
long id = addNote(dbNote);
notifyNotesChanged(); notifyNotesChanged();
getNoteServerSyncHelper().scheduleSync(true); getNoteServerSyncHelper().scheduleSync(true);
return id; return id;
@ -202,7 +312,7 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
* *
* @param note Note to be added. Remotely created Notes must be of type CloudNote and locally created Notes must be of Type DBNote (with DBStatus.LOCAL_EDITED)! * @param note Note to be added. Remotely created Notes must be of type CloudNote and locally created Notes must be of Type DBNote (with DBStatus.LOCAL_EDITED)!
*/ */
long addNote(CloudNote note) { long addNote(long accountId, CloudNote note) {
SQLiteDatabase db = this.getWritableDatabase(); SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
if (note instanceof DBNote) { if (note instanceof DBNote) {
@ -211,8 +321,12 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
values.put(key_id, dbNote.getId()); values.put(key_id, dbNote.getId());
} }
values.put(key_status, dbNote.getStatus().getTitle()); values.put(key_status, dbNote.getStatus().getTitle());
values.put(key_account_id, dbNote.getAccountId());
values.put(key_excerpt, dbNote.getExcerpt());
} else { } else {
values.put(key_status, DBStatus.VOID.getTitle()); values.put(key_status, DBStatus.VOID.getTitle());
values.put(key_account_id, accountId);
values.put(key_excerpt, NoteUtil.generateNoteExcerpt(note.getContent()));
} }
if (note.getRemoteId() > 0) { if (note.getRemoteId() > 0) {
values.put(key_remote_id, note.getRemoteId()); values.put(key_remote_id, note.getRemoteId());
@ -232,8 +346,8 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
* @param id int - ID of the requested Note * @param id int - ID of the requested Note
* @return requested Note * @return requested Note
*/ */
public DBNote getNote(long id) { public DBNote getNote(long accountId, long id) {
List<DBNote> notes = getNotesCustom(key_id + " = ? AND " + key_status + " != ?", new String[]{String.valueOf(id), DBStatus.LOCAL_DELETED.getTitle()}, null); List<DBNote> notes = getNotesCustom(accountId, key_id + " = ? AND " + key_status + " != ? AND " + key_account_id + " = ? ", new String[]{String.valueOf(id), DBStatus.LOCAL_DELETED.getTitle(), "" + accountId}, null, false);
return notes.isEmpty() ? null : notes.get(0); return notes.isEmpty() ? null : notes.get(0);
} }
@ -247,21 +361,21 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
*/ */
@NonNull @NonNull
@WorkerThread @WorkerThread
private List<DBNote> getNotesCustom(@NonNull String selection, @NonNull String[] selectionArgs, @Nullable String orderBy) { private List<DBNote> getNotesCustom(long accountId, @NonNull String selection, @NonNull String[] selectionArgs, @Nullable String orderBy, boolean pruneContent) {
return this.getNotesCustom(selection, selectionArgs, orderBy, null); return this.getNotesCustom(accountId, selection, selectionArgs, orderBy, null, pruneContent);
} }
@NonNull @NonNull
@WorkerThread @WorkerThread
private List<DBNote> getNotesCustom(@NonNull String selection, @NonNull String[] selectionArgs, @Nullable String orderBy, @Nullable String limit) { private List<DBNote> getNotesCustom(long accountId, @NonNull String selection, @NonNull String[] selectionArgs, @Nullable String orderBy, @Nullable String limit, boolean pruneContent) {
SQLiteDatabase db = getReadableDatabase(); SQLiteDatabase db = getReadableDatabase();
if (selectionArgs.length > 2) { if (selectionArgs.length > 2) {
Log.v("Note", selection + " ---- " + selectionArgs[0] + " " + selectionArgs[1] + " " + selectionArgs[2]); Log.v(TAG, selection + " ---- " + selectionArgs[0] + " " + selectionArgs[1] + " " + selectionArgs[2]);
} }
Cursor cursor = db.query(table_notes, columns, selection, selectionArgs, null, null, orderBy, limit); Cursor cursor = db.query(table_notes, pruneContent ? columnsWithoutContent : columns, selection, selectionArgs, null, null, orderBy, limit);
List<DBNote> notes = new ArrayList<>(); List<DBNote> notes = new ArrayList<>();
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
notes.add(getNoteFromCursor(cursor)); notes.add(getNoteFromCursor(accountId, cursor, pruneContent));
} }
cursor.close(); cursor.close();
return notes; return notes;
@ -271,29 +385,46 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
* Creates a DBNote object from the current row of a Cursor. * Creates a DBNote object from the current row of a Cursor.
* *
* @param cursor database cursor * @param cursor database cursor
* @param pruneContent
* @return DBNote * @return DBNote
*/ */
@NonNull @NonNull
private DBNote getNoteFromCursor(@NonNull Cursor cursor) { private DBNote getNoteFromCursor(long accountId, @NonNull Cursor cursor, boolean pruneContent) {
validateAccountId(accountId);
Calendar modified = Calendar.getInstance(); Calendar modified = Calendar.getInstance();
modified.setTimeInMillis(cursor.getLong(4) * 1000); modified.setTimeInMillis(cursor.getLong(4) * 1000);
return new DBNote(cursor.getLong(0), cursor.getLong(1), modified, cursor.getString(3), cursor.getString(5), cursor.getInt(6) > 0, cursor.getString(7), cursor.getString(8), DBStatus.parse(cursor.getString(2)));
return new DBNote(
cursor.getLong(0),
cursor.getLong(1),
modified,
cursor.getString(3),
pruneContent ? "" : cursor.getString(9),
cursor.getInt(5) > 0,
cursor.getString(6),
cursor.getString(7),
DBStatus.parse(cursor.getString(2)),
accountId,
cursor.getString(8)
);
} }
public void debugPrintFullDB() { public void debugPrintFullDB(long accountId) {
List<DBNote> notes = getNotesCustom("", new String[]{}, default_order); validateAccountId(accountId);
Log.v(getClass().getSimpleName(), "Full Database (" + notes.size() + " notes):"); List<DBNote> notes = getNotesCustom(accountId, "", new String[]{}, default_order, false);
Log.v(TAG, "Full Database (" + notes.size() + " notes):");
for (DBNote note : notes) { for (DBNote note : notes) {
Log.v(getClass().getSimpleName(), " " + note); Log.v(TAG, " " + note);
} }
} }
@NonNull @NonNull
@WorkerThread @WorkerThread
public Map<Long, Long> getIdMap() { public Map<Long, Long> getIdMap(long accountId) {
validateAccountId(accountId);
Map<Long, Long> result = new HashMap<>(); Map<Long, Long> result = new HashMap<>();
SQLiteDatabase db = getReadableDatabase(); SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(table_notes, new String[]{key_remote_id, key_id}, key_status + " != ?", new String[]{DBStatus.LOCAL_DELETED.getTitle()}, null, null, null); Cursor cursor = db.query(table_notes, new String[]{key_remote_id, key_id}, key_status + " != ? AND " + key_account_id + " = ? ", new String[]{DBStatus.LOCAL_DELETED.getTitle(), "" + accountId}, null, null, null);
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
result.put(cursor.getLong(0), cursor.getLong(1)); result.put(cursor.getLong(0), cursor.getLong(1));
} }
@ -308,14 +439,16 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
*/ */
@NonNull @NonNull
@WorkerThread @WorkerThread
public List<DBNote> getNotes() { public List<DBNote> getNotes(long accountId) {
return getNotesCustom(key_status + " != ?", new String[]{DBStatus.LOCAL_DELETED.getTitle()}, default_order); validateAccountId(accountId);
return getNotesCustom(accountId, key_status + " != ? AND " + key_account_id + " = ?", new String[]{DBStatus.LOCAL_DELETED.getTitle(), "" + accountId}, default_order, false);
} }
@NonNull @NonNull
@WorkerThread @WorkerThread
public List<DBNote> getRecentNotes() { public List<DBNote> getRecentNotes(long accountId) {
return getNotesCustom(key_status + " != ?", new String[]{DBStatus.LOCAL_DELETED.getTitle()}, key_modified + " DESC", "4"); validateAccountId(accountId);
return getNotesCustom(accountId, key_status + " != ? AND " + key_account_id + " = ?", new String[]{DBStatus.LOCAL_DELETED.getTitle(), "" + accountId}, key_modified + " DESC", "4", true);
} }
/** /**
@ -325,13 +458,17 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
*/ */
@NonNull @NonNull
@WorkerThread @WorkerThread
public List<DBNote> searchNotes(@Nullable CharSequence query, @Nullable String category, @Nullable Boolean favorite) { public List<DBNote> searchNotes(long accountId, @Nullable CharSequence query, @Nullable String category, @Nullable Boolean favorite) {
validateAccountId(accountId);
List<String> where = new ArrayList<>(); List<String> where = new ArrayList<>();
List<String> args = new ArrayList<>(); List<String> args = new ArrayList<>();
where.add(key_status + " != ?"); where.add(key_status + " != ?");
args.add(DBStatus.LOCAL_DELETED.getTitle()); args.add(DBStatus.LOCAL_DELETED.getTitle());
where.add(key_account_id + " = ?");
args.add("" + accountId);
if (query != null) { if (query != null) {
where.add(key_status + " != ?"); where.add(key_status + " != ?");
args.add(DBStatus.LOCAL_DELETED.getTitle()); args.add(DBStatus.LOCAL_DELETED.getTitle());
@ -354,7 +491,7 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
} }
String order = category == null ? default_order : key_category + ", " + key_title; String order = category == null ? default_order : key_category + ", " + key_title;
return getNotesCustom(TextUtils.join(" AND ", where), args.toArray(new String[]{}), order); return getNotesCustom(accountId, TextUtils.join(" AND ", where), args.toArray(new String[]{}), order, true);
} }
/** /**
@ -364,19 +501,21 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
*/ */
@NonNull @NonNull
@WorkerThread @WorkerThread
public List<DBNote> getLocalModifiedNotes() { List<DBNote> getLocalModifiedNotes(long accountId) {
return getNotesCustom(key_status + " != ?", new String[]{DBStatus.VOID.getTitle()}, null); validateAccountId(accountId);
return getNotesCustom(accountId, key_status + " != ? AND " + key_account_id + " = ?", new String[]{DBStatus.VOID.getTitle(), "" + accountId}, null, false);
} }
@NonNull @NonNull
@WorkerThread @WorkerThread
public Map<String, Integer> getFavoritesCount() { public Map<String, Integer> getFavoritesCount(long accountId) {
validateAccountId(accountId);
SQLiteDatabase db = getReadableDatabase(); SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query( Cursor cursor = db.query(
table_notes, table_notes,
new String[]{key_favorite, "COUNT(*)"}, new String[]{key_favorite, "COUNT(*)"},
key_status + " != ?", key_status + " != ? AND " + key_account_id + " = ?",
new String[]{DBStatus.LOCAL_DELETED.getTitle()}, new String[]{DBStatus.LOCAL_DELETED.getTitle(), "" + accountId},
key_favorite, key_favorite,
null, null,
key_favorite); key_favorite);
@ -390,19 +529,30 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
@NonNull @NonNull
@WorkerThread @WorkerThread
public List<NavigationAdapter.NavigationItem> getCategories() { public List<NavigationAdapter.NavigationItem> getCategories(long accountId) {
validateAccountId(accountId);
SQLiteDatabase db = getReadableDatabase(); SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query( Cursor cursor = db.query(
table_notes, table_notes,
new String[]{key_category, "COUNT(*)"}, new String[]{key_category, "COUNT(*)"},
key_status + " != ?", key_status + " != ? AND " + key_account_id + " = ?",
new String[]{DBStatus.LOCAL_DELETED.getTitle()}, new String[]{DBStatus.LOCAL_DELETED.getTitle(), "" + accountId},
key_category, key_category,
null, null,
key_category); key_category);
List<NavigationAdapter.NavigationItem> categories = new ArrayList<>(cursor.getCount()); List<NavigationAdapter.NavigationItem> categories = new ArrayList<>(cursor.getCount());
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
categories.add(new NavigationAdapter.NavigationItem("category:" + cursor.getString(0), cursor.getString(0), cursor.getInt(1), NavigationAdapter.ICON_FOLDER)); Resources res = context.getResources();
String category = cursor.getString(0).toLowerCase();
int icon = NavigationAdapter.ICON_FOLDER;
if (category.equals(res.getString(R.string.category_music).toLowerCase())) {
icon = R.drawable.ic_library_music_grey600_24dp;
} else if (category.equals(res.getString(R.string.category_movies).toLowerCase()) || category.equals(res.getString(R.string.category_movie).toLowerCase())) {
icon = R.drawable.ic_local_movies_grey600_24dp;
} else if (category.equals(res.getString(R.string.category_work).toLowerCase())) {
icon = R.drawable.ic_work_grey600_24dp;
}
categories.add(new NavigationAdapter.NavigationItem("category:" + cursor.getString(0), cursor.getString(0), cursor.getInt(1), icon));
} }
cursor.close(); cursor.close();
return categories; return categories;
@ -445,13 +595,13 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
* @param callback When the synchronization is finished, this callback will be invoked (optional). * @param callback When the synchronization is finished, this callback will be invoked (optional).
* @return changed note if differs from database, otherwise the old note. * @return changed note if differs from database, otherwise the old note.
*/ */
public DBNote updateNoteAndSync(@NonNull DBNote oldNote, @Nullable String newContent, @Nullable ICallback callback) { public DBNote updateNoteAndSync(long accountId, @NonNull DBNote oldNote, @Nullable String newContent, @Nullable ICallback callback) {
//debugPrintFullDB(); //debugPrintFullDB();
DBNote newNote; DBNote newNote;
if (newContent == null) { if (newContent == null) {
newNote = new DBNote(oldNote.getId(), oldNote.getRemoteId(), oldNote.getModified(), oldNote.getTitle(), oldNote.getContent(), oldNote.isFavorite(), oldNote.getCategory(), oldNote.getEtag(), DBStatus.LOCAL_EDITED); newNote = new DBNote(oldNote.getId(), oldNote.getRemoteId(), oldNote.getModified(), oldNote.getTitle(), oldNote.getContent(), oldNote.isFavorite(), oldNote.getCategory(), oldNote.getEtag(), DBStatus.LOCAL_EDITED, accountId, oldNote.getExcerpt());
} else { } else {
newNote = new DBNote(oldNote.getId(), oldNote.getRemoteId(), Calendar.getInstance(), NoteUtil.generateNonEmptyNoteTitle(newContent, getContext()), newContent, oldNote.isFavorite(), oldNote.getCategory(), oldNote.getEtag(), DBStatus.LOCAL_EDITED); newNote = new DBNote(oldNote.getId(), oldNote.getRemoteId(), Calendar.getInstance(), NoteUtil.generateNonEmptyNoteTitle(newContent, getContext()), newContent, oldNote.isFavorite(), oldNote.getCategory(), oldNote.getEtag(), DBStatus.LOCAL_EDITED, accountId, NoteUtil.generateNoteExcerpt(newContent));
} }
SQLiteDatabase db = this.getWritableDatabase(); SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
@ -460,6 +610,7 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
values.put(key_category, newNote.getCategory()); values.put(key_category, newNote.getCategory());
values.put(key_modified, newNote.getModified().getTimeInMillis() / 1000); values.put(key_modified, newNote.getModified().getTimeInMillis() / 1000);
values.put(key_content, newNote.getContent()); values.put(key_content, newNote.getContent());
values.put(key_excerpt, newNote.getExcerpt());
int rows = db.update(table_notes, values, key_id + " = ? AND (" + key_content + " != ? OR " + key_category + " != ?)", new String[]{String.valueOf(newNote.getId()), newNote.getContent(), newNote.getCategory()}); int rows = db.update(table_notes, values, key_id + " = ? AND (" + key_content + " != ? OR " + key_category + " != ?)", new String[]{String.valueOf(newNote.getId()), newNote.getContent(), newNote.getCategory()});
// if data was changed, set new status and schedule sync (with callback); otherwise invoke callback directly. // if data was changed, set new status and schedule sync (with callback); otherwise invoke callback directly.
if (rows > 0) { if (rows > 0) {
@ -485,9 +636,8 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
* @param id local ID of Note * @param id local ID of Note
* @param remoteNote Note from the server. * @param remoteNote Note from the server.
* @param forceUnchangedDBNoteState is not null, then the local note is updated only if it was not modified meanwhile * @param forceUnchangedDBNoteState is not null, then the local note is updated only if it was not modified meanwhile
* @return The number of the Rows affected.
*/ */
int updateNote(long id, @NonNull CloudNote remoteNote, @Nullable DBNote forceUnchangedDBNoteState) { void updateNote(long id, @NonNull CloudNote remoteNote, @Nullable DBNote forceUnchangedDBNoteState) {
SQLiteDatabase db = this.getWritableDatabase(); SQLiteDatabase db = this.getWritableDatabase();
// First, update the remote ID, since this field cannot be changed in parallel, but have to be updated always. // First, update the remote ID, since this field cannot be changed in parallel, but have to be updated always.
@ -505,6 +655,7 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
values.put(key_favorite, remoteNote.isFavorite()); values.put(key_favorite, remoteNote.isFavorite());
values.put(key_category, remoteNote.getCategory()); values.put(key_category, remoteNote.getCategory());
values.put(key_etag, remoteNote.getEtag()); values.put(key_etag, remoteNote.getEtag());
values.put(key_excerpt, NoteUtil.generateNoteExcerpt(remoteNote.getContent()));
String whereClause; String whereClause;
String[] whereArgs; String[] whereArgs;
if (forceUnchangedDBNoteState != null) { if (forceUnchangedDBNoteState != null) {
@ -521,8 +672,7 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
whereArgs = new String[]{String.valueOf(id), DBStatus.VOID.getTitle(), Long.toString(remoteNote.getModified().getTimeInMillis() / 1000), remoteNote.getTitle(), remoteNote.isFavorite() ? "1" : "0", remoteNote.getCategory(), remoteNote.getEtag(), remoteNote.getContent()}; whereArgs = new String[]{String.valueOf(id), DBStatus.VOID.getTitle(), Long.toString(remoteNote.getModified().getTimeInMillis() / 1000), remoteNote.getTitle(), remoteNote.isFavorite() ? "1" : "0", remoteNote.getCategory(), remoteNote.getEtag(), remoteNote.getContent()};
} }
int i = db.update(table_notes, values, whereClause, whereArgs); int i = db.update(table_notes, values, whereClause, whereArgs);
Log.d(getClass().getSimpleName(), "updateNote: " + remoteNote + " || forceUnchangedDBNoteState: " + forceUnchangedDBNoteState + " => " + i + " rows updated"); Log.d(TAG, "updateNote: " + remoteNote + " || forceUnchangedDBNoteState: " + forceUnchangedDBNoteState + " => " + i + " rows updated");
return i;
} }
/** /**
@ -530,10 +680,8 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
* from the Server. * from the Server.
* *
* @param id long - ID of the Note that should be deleted * @param id long - ID of the Note that should be deleted
* @return Affected rows
*/ */
@SuppressWarnings("UnusedReturnValue") public void deleteNoteAndSync(long id) {
public int deleteNoteAndSync(long id) {
SQLiteDatabase db = this.getWritableDatabase(); SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(key_status, DBStatus.LOCAL_DELETED.getTitle()); values.put(key_status, DBStatus.LOCAL_DELETED.getTitle());
@ -549,12 +697,11 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
shortcutManager.getPinnedShortcuts().forEach((shortcut) -> { shortcutManager.getPinnedShortcuts().forEach((shortcut) -> {
String shortcutId = id + ""; String shortcutId = id + "";
if (shortcut.getId().equals(shortcutId)) { if (shortcut.getId().equals(shortcutId)) {
Log.v(NoteSQLiteOpenHelper.class.getSimpleName(), "Removing shortcut for " + shortcutId); Log.v(TAG, "Removing shortcut for " + shortcutId);
shortcutManager.disableShortcuts(Collections.singletonList(shortcutId), context.getResources().getString(R.string.note_has_been_deleted)); shortcutManager.disableShortcuts(Collections.singletonList(shortcutId), context.getResources().getString(R.string.note_has_been_deleted));
} }
}); });
} }
return i;
} }
/** /**
@ -575,25 +722,157 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
* Notify about changed notes. * Notify about changed notes.
*/ */
void notifyNotesChanged() { void notifyNotesChanged() {
updateSingleNoteWidgets(); updateSingleNoteWidgets(getContext());
updateNoteListWidgets(); updateNoteListWidgets(getContext());
} }
/** /**
* Update single note widget, if the note data was changed. * Update single note widget, if the note data was changed.
*/ */
private void updateSingleNoteWidgets() { private static void updateSingleNoteWidgets(Context context) {
Intent intent = new Intent(getContext(), SingleNoteWidget.class); Intent intent = new Intent(context, SingleNoteWidget.class);
intent.setAction("android.appwidget.action.APPWIDGET_UPDATE"); intent.setAction("android.appwidget.action.APPWIDGET_UPDATE");
getContext().sendBroadcast(intent); context.sendBroadcast(intent);
} }
/** /**
* Update note list widgets, if the note data was changed. * Update note list widgets, if the note data was changed.
*/ */
private void updateNoteListWidgets() { private static void updateNoteListWidgets(Context context) {
Intent intent = new Intent(getContext(), NoteListWidget.class); Intent intent = new Intent(context, NoteListWidget.class);
intent.setAction("android.appwidget.action.APPWIDGET_UPDATE"); intent.setAction("android.appwidget.action.APPWIDGET_UPDATE");
getContext().sendBroadcast(intent); context.sendBroadcast(intent);
}
public boolean hasAccounts() {
return DatabaseUtils.queryNumEntries(getReadableDatabase(), table_accounts) > 0;
}
/**
* @param url URL to the root of the used Nextcloud instance without trailing slash
* @param username Username of the account
* @param accountName Composed by the username and the host of the URL, separated by @-sign
* @throws SQLiteConstraintException in case accountName already exists
*/
public void addAccount(@NonNull String url, @NonNull String username, @NonNull String accountName) throws SQLiteConstraintException {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(key_url, url);
values.put(key_username, username);
values.put(key_account_name, accountName);
db.insertOrThrow(table_accounts, null, values);
}
/**
* @param accountId account which should be read
* @return a LocalAccount object for the given accountId
*/
public LocalAccount getAccount(long accountId) {
validateAccountId(accountId);
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(table_accounts, new String[]{key_id, key_url, key_account_name, key_username, key_etag, key_modified}, key_id + " = ?", new String[]{accountId + ""}, null, null, null, null);
LocalAccount account = new LocalAccount();
while (cursor.moveToNext()) {
account.setId(cursor.getLong(0));
account.setUrl(cursor.getString(1));
account.setAccountName(cursor.getString(2));
account.setUserName(cursor.getString(3));
account.setETag(cursor.getString(4));
account.setModified(cursor.getLong(5));
}
cursor.close();
return account;
}
public List<LocalAccount> getAccounts() {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(table_accounts, new String[]{key_id, key_url, key_account_name, key_username, key_etag, key_modified}, null, null, null, null, null);
List<LocalAccount> accounts = new ArrayList<>();
while (cursor.moveToNext()) {
LocalAccount account = new LocalAccount();
account.setId(cursor.getLong(0));
account.setUrl(cursor.getString(1));
account.setAccountName(cursor.getString(2));
account.setUserName(cursor.getString(3));
account.setETag(cursor.getString(4));
account.setModified(cursor.getLong(5));
accounts.add(account);
}
cursor.close();
return accounts;
}
@Nullable
public LocalAccount getLocalAccountByAccountName(String accountName) {
if (accountName == null) {
Log.e(TAG, "accountName is null");
return null;
}
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(table_accounts, new String[]{key_id, key_url, key_account_name, key_username, key_etag, key_modified}, key_account_name + " = ?", new String[]{accountName}, null, null, null, null);
LocalAccount account = new LocalAccount();
while (cursor.moveToNext()) {
account.setId(cursor.getLong(0));
account.setUrl(cursor.getString(1));
account.setAccountName(cursor.getString(2));
account.setUserName(cursor.getString(3));
account.setETag(cursor.getString(4));
account.setModified(cursor.getLong(5));
}
cursor.close();
return account;
}
/**
* @param accountId the id of the account that should be deleted
* @throws IllegalArgumentException if no account has been deleted by the given accountId
*/
public void deleteAccount(long accountId) throws IllegalArgumentException {
validateAccountId(accountId);
SQLiteDatabase db = this.getWritableDatabase();
int deletedAccounts = db.delete(table_accounts, key_id + " = ?", new String[]{accountId + ""});
if (deletedAccounts < 1) {
Log.e(TAG, "AccountId '" + accountId + "' did not delete any account");
throw new IllegalArgumentException("The given accountId does not delete any row");
} else if (deletedAccounts > 1) {
Log.e(TAG, "AccountId '" + accountId + "' deleted unexpectedly '" + deletedAccounts + "' accounts");
}
final int deletedNotes = db.delete(table_notes, key_account_id + " = ?", new String[]{accountId + ""});
Log.v(TAG, "Deleted " + deletedNotes + " notes from account " + accountId);
}
void updateETag(long accountId, String etag) {
validateAccountId(accountId);
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(key_etag, etag);
final int updatedRows = db.update(table_accounts, values, key_id + " = ?", new String[]{accountId + ""});
if (updatedRows == 1) {
Log.v(TAG, "Updated etag to " + etag + " for accountId = " + accountId);
} else {
Log.e(TAG, "Updated " + updatedRows + " but expected only 1 for accountId = " + accountId + " and etag = " + etag);
}
}
void updateModified(long accountId, long modified) {
validateAccountId(accountId);
if (modified < 0) {
throw new IllegalArgumentException("modified must be greater or equal 0");
}
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(key_modified, modified);
final int updatedRows = db.update(table_accounts, values, key_id + " = ?", new String[]{accountId + ""});
if (updatedRows == 1) {
Log.v(TAG, "Updated modified to " + modified + " for accountId = " + accountId);
} else {
Log.e(TAG, "Updated " + updatedRows + " but expected only 1 for accountId = " + accountId + " and modified = " + modified);
}
}
private static void validateAccountId(long accountId) {
if (accountId < 1) {
throw new IllegalArgumentException("accountId must be greater than 0");
}
} }
} }

View file

@ -1,69 +1,52 @@
package it.niedermann.owncloud.notes.persistence; package it.niedermann.owncloud.notes.persistence;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.IBinder;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
import com.nextcloud.android.sso.exceptions.NextcloudApiNotRespondingException;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException;
import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
import com.nextcloud.android.sso.helper.SingleAccountHelper;
import org.json.JSONException; import org.json.JSONException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import at.bitfire.cert4android.CustomCertManager;
import at.bitfire.cert4android.CustomCertService;
import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.activity.SettingsActivity;
import it.niedermann.owncloud.notes.model.CloudNote; import it.niedermann.owncloud.notes.model.CloudNote;
import it.niedermann.owncloud.notes.model.DBNote; import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.model.DBStatus; import it.niedermann.owncloud.notes.model.DBStatus;
import it.niedermann.owncloud.notes.model.LocalAccount;
import it.niedermann.owncloud.notes.model.LoginStatus;
import it.niedermann.owncloud.notes.util.ICallback; import it.niedermann.owncloud.notes.util.ICallback;
import it.niedermann.owncloud.notes.util.NotesClient;
import it.niedermann.owncloud.notes.util.NotesClientUtil.LoginStatus;
import it.niedermann.owncloud.notes.util.ServerResponse; import it.niedermann.owncloud.notes.util.ServerResponse;
import it.niedermann.owncloud.notes.util.SupportUtil;
/** /**
* Helps to synchronize the Database to the Server. * Helps to synchronize the Database to the Server.
*/ */
public class NoteServerSyncHelper { public class NoteServerSyncHelper {
private static final String TAG = NoteServerSyncHelper.class.getSimpleName();
private static NoteServerSyncHelper instance; private static NoteServerSyncHelper instance;
/** private NoteSQLiteOpenHelper dbHelper;
* Get (or create) instance from NoteServerSyncHelper. private Context appContext = null;
* This has to be a singleton in order to realize correct registering and unregistering of private LocalAccount localAccount;
* the BroadcastReceiver, which listens on changes of network connectivity.
*
* @param dbHelper NoteSQLiteOpenHelper
* @return NoteServerSyncHelper
*/
public static synchronized NoteServerSyncHelper getInstance(NoteSQLiteOpenHelper dbHelper) {
if (instance == null) {
instance = new NoteServerSyncHelper(dbHelper);
}
return instance;
}
private final NoteSQLiteOpenHelper dbHelper;
private final Context appContext;
private CustomCertManager customCertManager;
// Track network connection changes using a BroadcastReceiver // Track network connection changes using a BroadcastReceiver
private boolean networkConnected = false; private boolean networkConnected = false;
@ -90,25 +73,10 @@ public class NoteServerSyncHelper {
} }
}; };
private boolean cert4androidReady = false;
private final ServiceConnection certService = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
cert4androidReady = true;
if (isSyncPossible()) {
scheduleSync(false);
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
cert4androidReady = false;
}
};
// current state of the synchronization // current state of the synchronization
private boolean syncActive = false; private boolean syncActive = false;
private boolean syncScheduled = false; private boolean syncScheduled = false;
private NotesClient notesClient;
// list of callbacks for both parts of synchronziation // list of callbacks for both parts of synchronziation
private List<ICallback> callbacksPush = new ArrayList<>(); private List<ICallback> callbacksPush = new ArrayList<>();
@ -118,13 +86,12 @@ public class NoteServerSyncHelper {
private NoteServerSyncHelper(NoteSQLiteOpenHelper db) { private NoteServerSyncHelper(NoteSQLiteOpenHelper db) {
this.dbHelper = db; this.dbHelper = db;
this.appContext = db.getContext().getApplicationContext(); this.appContext = db.getContext().getApplicationContext();
try {
updateAccount();
} catch (NextcloudFilesAppAccountNotFoundException e) {
e.printStackTrace();
}
this.syncOnlyOnWifiKey = appContext.getResources().getString(R.string.pref_key_wifi_only); this.syncOnlyOnWifiKey = appContext.getResources().getString(R.string.pref_key_wifi_only);
new Thread() {
@Override
public void run() {
customCertManager = SupportUtil.getCertManager(appContext);
}
}.start();
// Registers BroadcastReceiver to track network connection changes. // Registers BroadcastReceiver to track network connection changes.
appContext.registerReceiver(networkReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); appContext.registerReceiver(networkReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
@ -134,38 +101,67 @@ public class NoteServerSyncHelper {
syncOnlyOnWifi = prefs.getBoolean(syncOnlyOnWifiKey, false); syncOnlyOnWifi = prefs.getBoolean(syncOnlyOnWifiKey, false);
updateNetworkStatus(); updateNetworkStatus();
// bind to certifciate service to block sync attempts if service is not ready }
appContext.bindService(new Intent(appContext, CustomCertService.class), certService, Context.BIND_AUTO_CREATE);
/**
* Get (or create) instance from NoteServerSyncHelper.
* This has to be a singleton in order to realize correct registering and unregistering of
* the BroadcastReceiver, which listens on changes of network connectivity.
*
* @param dbHelper NoteSQLiteOpenHelper
* @return NoteServerSyncHelper
*/
public static synchronized NoteServerSyncHelper getInstance(NoteSQLiteOpenHelper dbHelper) {
if (instance == null) {
instance = new NoteServerSyncHelper(dbHelper);
}
return instance;
}
public void updateAccount() throws NextcloudFilesAppAccountNotFoundException {
try {
this.localAccount = dbHelper.getLocalAccountByAccountName(SingleAccountHelper.getCurrentSingleSignOnAccount(appContext).name);
if (notesClient == null) {
if (this.localAccount != null) {
notesClient = new NotesClient(appContext);
}
} else {
notesClient.updateAccount();
}
Log.v(TAG, "NextcloudRequest account: " + localAccount);
} catch (NoCurrentAccountSelectedException e) {
e.printStackTrace();
}
Log.v(TAG, "Reinstanziation NotesClient because of SSO acc changed");
} }
@Override @Override
protected void finalize() throws Throwable { protected void finalize() throws Throwable {
appContext.unregisterReceiver(networkReceiver); appContext.unregisterReceiver(networkReceiver);
appContext.unbindService(certService);
if (customCertManager != null) {
customCertManager.close();
}
super.finalize(); super.finalize();
} }
public static boolean isConfigured(Context context) { public static boolean isConfigured(Context context) {
return !PreferenceManager.getDefaultSharedPreferences(context).getString(SettingsActivity.SETTINGS_URL, SettingsActivity.DEFAULT_SETTINGS).isEmpty(); try {
SingleAccountHelper.getCurrentSingleSignOnAccount(context);
return true;
} catch (NextcloudFilesAppAccountNotFoundException e) {
return false;
} catch (NoCurrentAccountSelectedException e) {
return false;
}
} }
/** /**
* Synchronization is only possible, if there is an active network connection and * Synchronization is only possible, if there is an active network connection and
* Cert4Android service is available. * SingleSignOn is available
* NoteServerSyncHelper observes changes in the network connection. * NoteServerSyncHelper observes changes in the network connection.
* The current state can be retrieved with this method. * The current state can be retrieved with this method.
* *
* @return true if sync is possible, otherwise false. * @return true if sync is possible, otherwise false.
*/ */
public boolean isSyncPossible() { public boolean isSyncPossible() {
return networkConnected && isConfigured(appContext) && cert4androidReady; return networkConnected && isConfigured(appContext);
}
public CustomCertManager getCustomCertManager() {
return customCertManager;
} }
/** /**
@ -200,10 +196,9 @@ public class NoteServerSyncHelper {
* @param onlyLocalChanges Whether to only push local changes to the server or to also load the whole list of notes from the server. * @param onlyLocalChanges Whether to only push local changes to the server or to also load the whole list of notes from the server.
*/ */
public void scheduleSync(boolean onlyLocalChanges) { public void scheduleSync(boolean onlyLocalChanges) {
Log.d(getClass().getSimpleName(), "Sync requested (" + (onlyLocalChanges ? "onlyLocalChanges" : "full") + "; " + (syncActive ? "sync active" : "sync NOT active") + ") ..."); Log.d(TAG, "Sync requested (" + (onlyLocalChanges ? "onlyLocalChanges" : "full") + "; " + (syncActive ? "sync active" : "sync NOT active") + ") ...");
Log.d(getClass().getSimpleName(), "(network:" + networkConnected + "; conf:" + isConfigured(appContext) + "; cert4android:" + cert4androidReady + ")");
if (isSyncPossible() && (!syncActive || onlyLocalChanges)) { if (isSyncPossible() && (!syncActive || onlyLocalChanges)) {
Log.d(getClass().getSimpleName(), "... starting now"); Log.d(TAG, "... starting now");
SyncTask syncTask = new SyncTask(onlyLocalChanges); SyncTask syncTask = new SyncTask(onlyLocalChanges);
syncTask.addCallbacks(callbacksPush); syncTask.addCallbacks(callbacksPush);
callbacksPush = new ArrayList<>(); callbacksPush = new ArrayList<>();
@ -213,13 +208,13 @@ public class NoteServerSyncHelper {
} }
syncTask.execute(); syncTask.execute();
} else if (!onlyLocalChanges) { } else if (!onlyLocalChanges) {
Log.d(getClass().getSimpleName(), "... scheduled"); Log.d(TAG, "... scheduled");
syncScheduled = true; syncScheduled = true;
for (ICallback callback : callbacksPush) { for (ICallback callback : callbacksPush) {
callback.onScheduled(); callback.onScheduled();
} }
} else { } else {
Log.d(getClass().getSimpleName(), "... do nothing"); Log.d(TAG, "... do nothing");
for (ICallback callback : callbacksPush) { for (ICallback callback : callbacksPush) {
callback.onScheduled(); callback.onScheduled();
} }
@ -237,13 +232,13 @@ public class NoteServerSyncHelper {
.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected(); .getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected();
if (networkConnected) { if (networkConnected) {
Log.d(NoteServerSyncHelper.class.getSimpleName(), "Network connection established."); Log.d(TAG, "Network connection established.");
} else { } else {
Log.d(NoteServerSyncHelper.class.getSimpleName(), "Network connected, but not used because only synced on wifi."); Log.d(TAG, "Network connected, but not used because only synced on wifi.");
} }
} else { } else {
networkConnected = false; networkConnected = false;
Log.d(NoteServerSyncHelper.class.getSimpleName(), "No network connection."); Log.d(TAG, "No network connection.");
} }
} }
@ -254,7 +249,6 @@ public class NoteServerSyncHelper {
private class SyncTask extends AsyncTask<Void, Void, LoginStatus> { private class SyncTask extends AsyncTask<Void, Void, LoginStatus> {
private final boolean onlyLocalChanges; private final boolean onlyLocalChanges;
private final List<ICallback> callbacks = new ArrayList<>(); private final List<ICallback> callbacks = new ArrayList<>();
private NotesClient client;
private List<Throwable> exceptions = new ArrayList<>(); private List<Throwable> exceptions = new ArrayList<>();
public SyncTask(boolean onlyLocalChanges) { public SyncTask(boolean onlyLocalChanges) {
@ -276,8 +270,7 @@ public class NoteServerSyncHelper {
@Override @Override
protected LoginStatus doInBackground(Void... voids) { protected LoginStatus doInBackground(Void... voids) {
client = createNotesClient(); // recreate NoteClients on every sync in case the connection settings was changed Log.i(TAG, "STARTING SYNCHRONIZATION");
Log.i(getClass().getSimpleName(), "STARTING SYNCHRONIZATION");
//dbHelper.debugPrintFullDB(); //dbHelper.debugPrintFullDB();
LoginStatus status = LoginStatus.OK; LoginStatus status = LoginStatus.OK;
pushLocalChanges(); pushLocalChanges();
@ -285,7 +278,7 @@ public class NoteServerSyncHelper {
status = pullRemoteChanges(); status = pullRemoteChanges();
} }
//dbHelper.debugPrintFullDB(); //dbHelper.debugPrintFullDB();
Log.i(getClass().getSimpleName(), "SYNCHRONIZATION FINISHED"); Log.i(TAG, "SYNCHRONIZATION FINISHED");
return status; return status;
} }
@ -293,42 +286,37 @@ public class NoteServerSyncHelper {
* Push local changes: for each locally created/edited/deleted Note, use NotesClient in order to push the changed to the server. * Push local changes: for each locally created/edited/deleted Note, use NotesClient in order to push the changed to the server.
*/ */
private void pushLocalChanges() { private void pushLocalChanges() {
Log.d(getClass().getSimpleName(), "pushLocalChanges()"); if (localAccount == null) {
List<DBNote> notes = dbHelper.getLocalModifiedNotes(); return;
}
Log.d(TAG, "pushLocalChanges()");
List<DBNote> notes = dbHelper.getLocalModifiedNotes(localAccount.getId());
for (DBNote note : notes) { for (DBNote note : notes) {
Log.d(getClass().getSimpleName(), " Process Local Note: " + note); Log.d(TAG, " Process Local Note: " + note);
try { try {
CloudNote remoteNote = null; CloudNote remoteNote = null;
switch (note.getStatus()) { switch (note.getStatus()) {
case LOCAL_EDITED: case LOCAL_EDITED:
Log.v(getClass().getSimpleName(), " ...create/edit"); Log.v(TAG, " ...create/edit");
// if note is not new, try to edit it. // if note is not new, try to edit it.
if (note.getRemoteId() > 0) { if (note.getRemoteId() > 0) {
Log.v(getClass().getSimpleName(), " ...try to edit"); Log.v(TAG, " ...try to edit");
try { remoteNote = notesClient.editNote(note).getNote();
remoteNote = client.editNote(customCertManager, note).getNote();
} catch (FileNotFoundException e) {
// Note does not exists anymore
}
} }
// However, the note may be deleted on the server meanwhile; or was never synchronized -> (re)create // However, the note may be deleted on the server meanwhile; or was never synchronized -> (re)create
// Please note, thas dbHelper.updateNote() realizes an optimistic conflict resolution, which is required for parallel changes of this Note from the UI. // Please note, thas dbHelper.updateNote() realizes an optimistic conflict resolution, which is required for parallel changes of this Note from the UI.
if (remoteNote == null) { if (remoteNote == null) {
Log.v(getClass().getSimpleName(), " ...Note does not exist on server -> (re)create"); Log.v(TAG, " ...Note does not exist on server -> (re)create");
remoteNote = client.createNote(customCertManager, note).getNote(); remoteNote = notesClient.createNote(note).getNote();
} }
dbHelper.updateNote(note.getId(), remoteNote, note); dbHelper.updateNote(note.getId(), remoteNote, note);
break; break;
case LOCAL_DELETED: case LOCAL_DELETED:
if (note.getRemoteId() > 0) { if (note.getRemoteId() > 0) {
Log.v(getClass().getSimpleName(), " ...delete (from server and local)"); Log.v(TAG, " ...delete (from server and local)");
try { notesClient.deleteNote(note.getRemoteId());
client.deleteNote(customCertManager, note.getRemoteId());
} catch (FileNotFoundException e) {
Log.v(getClass().getSimpleName(), " ...Note does not exist on server (anymore?) -> delete locally");
}
} else { } else {
Log.v(getClass().getSimpleName(), " ...delete (only local, since it was not synchronized)"); Log.v(TAG, " ...delete (only local, since it was not synchronized)");
} }
// Please note, thas dbHelper.deleteNote() realizes an optimistic conflict resolution, which is required for parallel changes of this Note from the UI. // Please note, thas dbHelper.deleteNote() realizes an optimistic conflict resolution, which is required for parallel changes of this Note from the UI.
dbHelper.deleteNote(note.getId(), DBStatus.LOCAL_DELETED); dbHelper.deleteNote(note.getId(), DBStatus.LOCAL_DELETED);
@ -336,9 +324,18 @@ public class NoteServerSyncHelper {
default: default:
throw new IllegalStateException("Unknown State of Note: " + note); throw new IllegalStateException("Unknown State of Note: " + note);
} }
} catch (IOException | JSONException e) { } catch (JSONException e) {
Log.e(getClass().getSimpleName(), "Exception", e); Log.e(TAG, "Exception", e);
exceptions.add(e); exceptions.add(e);
} catch (NextcloudHttpRequestFailedException e) {
if (e.getStatusCode() == 304) {
Log.d(TAG, "Server returned HTTP Status Code 304 - Not Modified");
} else {
e.printStackTrace();
}
} catch (NextcloudApiNotRespondingException e) {
Log.e(TAG, "Exception", e);
e.printStackTrace();
} }
} }
} }
@ -347,66 +344,59 @@ public class NoteServerSyncHelper {
* Pull remote Changes: update or create each remote note (if local pendant has no changes) and remove remotely deleted notes. * Pull remote Changes: update or create each remote note (if local pendant has no changes) and remove remotely deleted notes.
*/ */
private LoginStatus pullRemoteChanges() { private LoginStatus pullRemoteChanges() {
Log.d(getClass().getSimpleName(), "pullRemoteChanges()"); if (localAccount == null) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(appContext); return LoginStatus.NO_NETWORK;
String lastETag = preferences.getString(SettingsActivity.SETTINGS_KEY_ETAG, null); }
long lastModified = preferences.getLong(SettingsActivity.SETTINGS_KEY_LAST_MODIFIED, 0); Log.d(TAG, "pullRemoteChanges() for account " + localAccount.getAccountName());
LoginStatus status; LoginStatus status;
try { try {
Map<Long, Long> idMap = dbHelper.getIdMap(); Map<Long, Long> idMap = dbHelper.getIdMap(localAccount.getId());
ServerResponse.NotesResponse response = client.getNotes(customCertManager, lastModified, lastETag); ServerResponse.NotesResponse response = notesClient.getNotes(localAccount.getModified(), localAccount.getEtag());
List<CloudNote> remoteNotes = response.getNotes(); List<CloudNote> remoteNotes = response.getNotes();
Set<Long> remoteIDs = new HashSet<>(); Set<Long> remoteIDs = new HashSet<>();
// pull remote changes: update or create each remote note // pull remote changes: update or create each remote note
for (CloudNote remoteNote : remoteNotes) { for (CloudNote remoteNote : remoteNotes) {
Log.v(getClass().getSimpleName(), " Process Remote Note: " + remoteNote); Log.v(TAG, " Process Remote Note: " + remoteNote);
remoteIDs.add(remoteNote.getRemoteId()); remoteIDs.add(remoteNote.getRemoteId());
if (remoteNote.getModified() == null) { if (remoteNote.getModified() == null) {
Log.v(getClass().getSimpleName(), " ... unchanged"); Log.v(TAG, " ... unchanged");
} else if (idMap.containsKey(remoteNote.getRemoteId())) { } else if (idMap.containsKey(remoteNote.getRemoteId())) {
Log.v(getClass().getSimpleName(), " ... found -> Update"); Log.v(TAG, " ... found -> Update");
dbHelper.updateNote(idMap.get(remoteNote.getRemoteId()), remoteNote, null); dbHelper.updateNote(idMap.get(remoteNote.getRemoteId()), remoteNote, null);
} else { } else {
Log.v(getClass().getSimpleName(), " ... create"); Log.v(TAG, " ... create");
dbHelper.addNote(remoteNote); dbHelper.addNote(localAccount.getId(), remoteNote);
} }
} }
Log.d(getClass().getSimpleName(), " Remove remotely deleted Notes (only those without local changes)"); Log.d(TAG, " Remove remotely deleted Notes (only those without local changes)");
// remove remotely deleted notes (only those without local changes) // remove remotely deleted notes (only those without local changes)
for (Map.Entry<Long, Long> entry : idMap.entrySet()) { for (Map.Entry<Long, Long> entry : idMap.entrySet()) {
if (!remoteIDs.contains(entry.getKey())) { if (!remoteIDs.contains(entry.getKey())) {
Log.v(getClass().getSimpleName(), " ... remove " + entry.getValue()); Log.v(TAG, " ... remove " + entry.getValue());
dbHelper.deleteNote(entry.getValue(), DBStatus.VOID); dbHelper.deleteNote(entry.getValue(), DBStatus.VOID);
} }
} }
status = LoginStatus.OK;
// update ETag and Last-Modified in order to reduce size of next response // update ETag and Last-Modified in order to reduce size of next response
SharedPreferences.Editor editor = preferences.edit(); localAccount.setETag(response.getETag());
String etag = response.getETag(); localAccount.setModified(response.getLastModified());
if (etag != null && !etag.isEmpty()) { dbHelper.updateETag(localAccount.getId(), localAccount.getEtag());
editor.putString(SettingsActivity.SETTINGS_KEY_ETAG, etag); dbHelper.updateModified(localAccount.getId(), localAccount.getModified());
} else { return LoginStatus.OK;
editor.remove(SettingsActivity.SETTINGS_KEY_ETAG);
}
long modified = response.getLastModified();
if (modified != 0) {
editor.putLong(SettingsActivity.SETTINGS_KEY_LAST_MODIFIED, modified);
} else {
editor.remove(SettingsActivity.SETTINGS_KEY_LAST_MODIFIED);
}
editor.apply();
} catch (ServerResponse.NotModifiedException e) {
Log.d(getClass().getSimpleName(), "No changes, nothing to do.");
status = LoginStatus.OK;
} catch (IOException e) {
Log.e(getClass().getSimpleName(), "Exception", e);
exceptions.add(e);
status = LoginStatus.CONNECTION_FAILED;
} catch (JSONException e) { } catch (JSONException e) {
Log.e(getClass().getSimpleName(), "Exception", e); Log.e(TAG, "Exception", e);
exceptions.add(e); exceptions.add(e);
status = LoginStatus.JSON_FAILED; status = LoginStatus.JSON_FAILED;
} catch (NextcloudHttpRequestFailedException e) {
if (e.getStatusCode() == 304) {
Log.d(TAG, "Server returned HTTP Status Code 304 - Not Modified");
return LoginStatus.OK;
} else {
e.printStackTrace();
return LoginStatus.JSON_FAILED;
}
} catch (NextcloudApiNotRespondingException e) {
return LoginStatus.PROBLEM_WITH_FILES_APP;
} }
return status; return status;
} }
@ -432,12 +422,4 @@ public class NoteServerSyncHelper {
} }
} }
} }
private NotesClient createNotesClient() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(appContext.getApplicationContext());
String url = preferences.getString(SettingsActivity.SETTINGS_URL, SettingsActivity.DEFAULT_SETTINGS);
String username = preferences.getString(SettingsActivity.SETTINGS_USERNAME, SettingsActivity.DEFAULT_SETTINGS);
String password = preferences.getString(SettingsActivity.SETTINGS_PASSWORD, SettingsActivity.DEFAULT_SETTINGS);
return new NotesClient(url, username, password);
}
} }

View file

@ -0,0 +1,225 @@
package it.niedermann.owncloud.notes.persistence;
import android.content.Context;
import android.util.Log;
import androidx.annotation.WorkerThread;
import com.google.gson.GsonBuilder;
import com.nextcloud.android.sso.aidl.NextcloudRequest;
import com.nextcloud.android.sso.api.AidlNetworkRequest;
import com.nextcloud.android.sso.api.NextcloudAPI;
import com.nextcloud.android.sso.api.Response;
import com.nextcloud.android.sso.exceptions.NextcloudApiNotRespondingException;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException;
import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
import com.nextcloud.android.sso.helper.SingleAccountHelper;
import com.nextcloud.android.sso.model.SingleSignOnAccount;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import it.niedermann.owncloud.notes.model.CloudNote;
import it.niedermann.owncloud.notes.util.ServerResponse.NoteResponse;
import it.niedermann.owncloud.notes.util.ServerResponse.NotesResponse;
@WorkerThread
public class NotesClient {
private static final String TAG = NotesClient.class.getSimpleName();
private final Context context;
private NextcloudAPI mNextcloudAPI;
/**
* This entity class is used to return relevant data of the HTTP reponse.
*/
public static class ResponseData {
private final String content;
private final String etag;
private final long lastModified;
public ResponseData(String content, String etag, long lastModified) {
this.content = content;
this.etag = etag;
this.lastModified = lastModified;
}
public String getContent() {
return content;
}
public String getETag() {
return etag;
}
public long getLastModified() {
return lastModified;
}
}
private static final String API_PATH = "/index.php/apps/notes/api/v0.2/";
private static final String GET_PARAM_KEY_PRUNE_BEFORE = "pruneBefore";
private static final String HEADER_KEY_ETAG = "ETag";
private static final String HEADER_KEY_LAST_MODIFIED = "Last-Modified";
private static final String HEADER_KEY_CONTENT_TYPE = "Content-Type";
private static final String HEADER_KEY_IF_NONE_MATCH = "If-None-Match";
private static final String HEADER_VALUE_APPLICATION_JSON = "application/json";
private static final String METHOD_GET = "GET";
private static final String METHOD_PUT = "PUT";
private static final String METHOD_POST = "POST";
private static final String METHOD_DELETE = "DELETE";
public static final String JSON_ID = "id";
public static final String JSON_TITLE = "title";
public static final String JSON_CONTENT = "content";
public static final String JSON_FAVORITE = "favorite";
public static final String JSON_CATEGORY = "category";
public static final String JSON_ETAG = "etag";
public static final String JSON_MODIFIED = "modified";
NotesClient(Context context) {
this.context = context;
updateAccount();
}
void updateAccount() {
if(mNextcloudAPI != null) {
mNextcloudAPI.stop();
}
try {
SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);
Log.v(TAG, "NextcloudRequest account: " + ssoAccount.name);
mNextcloudAPI = new NextcloudAPI(context, ssoAccount, new GsonBuilder().create(), new NextcloudAPI.ApiConnectedListener() {
@Override
public void onConnected() {
Log.v(TAG, "SSO API connected");
}
@Override
public void onError(Exception ex) {
ex.printStackTrace();
}
});
} catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
e.printStackTrace();
}
}
NotesResponse getNotes(long lastModified, String lastETag) throws NextcloudHttpRequestFailedException, NextcloudApiNotRespondingException {
Map<String, String> parameter = new HashMap<>();
parameter.put(GET_PARAM_KEY_PRUNE_BEFORE, Long.toString(lastModified));
return new NotesResponse(requestServer("notes", METHOD_GET, parameter, null, lastETag));
}
private NoteResponse putNote(CloudNote note, String path, String method) throws JSONException, NextcloudHttpRequestFailedException, NextcloudApiNotRespondingException {
JSONObject paramObject = new JSONObject();
paramObject.accumulate(JSON_CONTENT, note.getContent());
paramObject.accumulate(JSON_MODIFIED, note.getModified().getTimeInMillis() / 1000);
paramObject.accumulate(JSON_FAVORITE, note.isFavorite());
paramObject.accumulate(JSON_CATEGORY, note.getCategory());
return new NoteResponse(requestServer(path, method, null, paramObject, null));
}
/**
* Creates a Note on the Server
*
* @param note {@link CloudNote} - the new Note
* @return Created Note including generated Title, ID and lastModified-Date
* @throws JSONException
* @throws NextcloudHttpRequestFailedException
*/
NoteResponse createNote(CloudNote note) throws JSONException, NextcloudHttpRequestFailedException, NextcloudApiNotRespondingException {
return putNote(note, "notes", METHOD_POST);
}
NoteResponse editNote(CloudNote note) throws JSONException, NextcloudHttpRequestFailedException, NextcloudApiNotRespondingException {
return putNote(note, "notes/" + note.getRemoteId(), METHOD_PUT);
}
void deleteNote(long noteId) {
try {
this.requestServer("notes/" + noteId, METHOD_DELETE, null, null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Request-Method for POST, PUT with or without JSON-Object-Parameter
*
* @param target Filepath to the wanted function
* @param method GET, POST, DELETE or PUT
* @param parameter optional headers to be sent
* @param requestBody JSON Object which shall be transferred to the server.
* @param lastETag optional ETag of last response
* @return Body of answer
*/
private ResponseData requestServer(String target, String method, Map<String, String> parameter, JSONObject requestBody, String lastETag) throws NextcloudHttpRequestFailedException, NextcloudApiNotRespondingException {
NextcloudRequest.Builder requestBuilder = new NextcloudRequest.Builder()
.setMethod(method)
.setUrl(API_PATH + target);
if(parameter != null) {
requestBuilder.setParameter(parameter);
}
Map<String, List<String>> header = new HashMap<>();
if (requestBody != null) {
header.put(HEADER_KEY_CONTENT_TYPE, Collections.singletonList(HEADER_VALUE_APPLICATION_JSON));
requestBuilder.setRequestBody(requestBody.toString());
}
if (lastETag != null && !lastETag.isEmpty() && METHOD_GET.equals(method)) {
header.put(HEADER_KEY_IF_NONE_MATCH, Collections.singletonList('"' + lastETag + '"'));
requestBuilder.setHeader(header);
}
NextcloudRequest nextcloudRequest = requestBuilder.build();
StringBuilder result = new StringBuilder();
try {
Log.v(TAG, "NextcloudRequest: " + nextcloudRequest.toString());
Response response = mNextcloudAPI.performNetworkRequestV2(nextcloudRequest);
Log.v(TAG, "NextcloudRequest: " + nextcloudRequest.toString());
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getBody()));
String line;
while ((line = rd.readLine()) != null) {
result.append(line);
}
response.getBody().close();
String etag = "";
AidlNetworkRequest.PlainHeader eTagHeader = response.getPlainHeader(HEADER_KEY_ETAG);
if (eTagHeader != null) {
etag = Objects.requireNonNull(eTagHeader.getValue()).replace("\"", "");
}
long lastModified = 0;
AidlNetworkRequest.PlainHeader lastModifiedHeader = response.getPlainHeader(HEADER_KEY_LAST_MODIFIED);
if (lastModifiedHeader != null)
lastModified = new Date(lastModifiedHeader.getValue()).getTime() / 1000;
Log.d(TAG, "ETag: " + etag + "; Last-Modified: " + lastModified + " (" + lastModified + ")");
// return these header fields since they should only be saved after successful processing the result!
return new ResponseData(result.toString(), etag, lastModified);
} catch(NextcloudApiNotRespondingException | NextcloudHttpRequestFailedException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

View file

@ -0,0 +1,40 @@
package it.niedermann.owncloud.notes.util;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import androidx.annotation.NonNull;
public class DatabaseIndexUtil {
private static final String TAG = DatabaseIndexUtil.class.getSimpleName();
private DatabaseIndexUtil() {
}
public static void createIndex(@NonNull SQLiteDatabase db, @NonNull String table, @NonNull String ...columns) {
for (String column: columns) {
createIndex(db, table, column);
}
}
public static void createIndex(@NonNull SQLiteDatabase db, @NonNull String table, @NonNull String column) {
String indexName = table + "_" + column + "_idx";
Log.v(TAG, "Creating database index: CREATE INDEX IF NOT EXISTS " + indexName + " ON " + table + "(" + column + ")");
db.execSQL("CREATE INDEX IF NOT EXISTS " + indexName + " ON " + table + "(" + column + ")");
}
public static void dropIndexes(@NonNull SQLiteDatabase db) {
try (Cursor c = db.query("sqlite_master", new String[]{"name", "sql"}, "type=?", new String[]{"index"}, null, null, null)) {
while (c.moveToNext()) {
// Skip automatic indexes which we can't drop manually
if (c.getString(1) != null) {
Log.v(TAG, "Deleting database index: DROP INDEX " + c.getString(0));
db.execSQL("DROP INDEX " + c.getString(0));
}
}
}
}
}

View file

@ -26,16 +26,20 @@ import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import androidx.annotation.ColorInt;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import androidx.annotation.ColorInt;
public class DisplayUtils { public class DisplayUtils {
private DisplayUtils() {
}
public static Spannable searchAndColor(String text, Spannable spannable, String searchText, @ColorInt int color) { public static Spannable searchAndColor(String text, Spannable spannable, String searchText, @ColorInt int color) {
Object spansToRemove[] = spannable.getSpans(0, text.length(), Object.class); Object[] spansToRemove = spannable.getSpans(0, text.length(), Object.class);
for(Object span: spansToRemove){ for(Object span: spansToRemove){
if(span instanceof CharacterStyle) if(span instanceof CharacterStyle)
spannable.removeSpan(span); spannable.removeSpan(span);

View file

@ -1,6 +1,7 @@
package it.niedermann.owncloud.notes.util; package it.niedermann.owncloud.notes.util;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -13,6 +14,7 @@ import it.niedermann.owncloud.notes.R;
* Created by stefan on 06.10.15. * Created by stefan on 06.10.15.
*/ */
public class NoteUtil { public class NoteUtil {
private static final Pattern pLists = Pattern.compile("^\\s*[*+-]\\s+", Pattern.MULTILINE); private static final Pattern pLists = Pattern.compile("^\\s*[*+-]\\s+", Pattern.MULTILINE);
private static final Pattern pHeadings = Pattern.compile("^#+\\s+(.*?)\\s*#*$", Pattern.MULTILINE); private static final Pattern pHeadings = Pattern.compile("^#+\\s+(.*?)\\s*#*$", Pattern.MULTILINE);
private static final Pattern pHeadingLine = Pattern.compile("^(?:=*|-*)$", Pattern.MULTILINE); private static final Pattern pHeadingLine = Pattern.compile("^(?:=*|-*)$", Pattern.MULTILINE);
@ -20,6 +22,9 @@ public class NoteUtil {
private static final Pattern pSpace1 = Pattern.compile("^\\s+", Pattern.MULTILINE); private static final Pattern pSpace1 = Pattern.compile("^\\s+", Pattern.MULTILINE);
private static final Pattern pSpace2 = Pattern.compile("\\s+$", Pattern.MULTILINE); private static final Pattern pSpace2 = Pattern.compile("\\s+$", Pattern.MULTILINE);
private NoteUtil() {
}
/** /**
* Strips all MarkDown from the given String * Strips all MarkDown from the given String

View file

@ -1,188 +0,0 @@
package it.niedermann.owncloud.notes.util;
import androidx.annotation.WorkerThread;
import android.util.Base64;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import at.bitfire.cert4android.CustomCertManager;
import it.niedermann.owncloud.notes.BuildConfig;
import it.niedermann.owncloud.notes.model.CloudNote;
import it.niedermann.owncloud.notes.util.ServerResponse.NoteResponse;
import it.niedermann.owncloud.notes.util.ServerResponse.NotesResponse;
@WorkerThread
public class NotesClient {
/**
* This entity class is used to return relevant data of the HTTP reponse.
*/
public static class ResponseData {
private final String content;
private final String etag;
private final long lastModified;
public ResponseData(String content, String etag, long lastModified) {
this.content = content;
this.etag = etag;
this.lastModified = lastModified;
}
public String getContent() {
return content;
}
public String getETag() {
return etag;
}
public long getLastModified() {
return lastModified;
}
}
public static final String METHOD_GET = "GET";
public static final String METHOD_PUT = "PUT";
public static final String METHOD_POST = "POST";
public static final String METHOD_DELETE = "DELETE";
public static final String JSON_ID = "id";
public static final String JSON_TITLE = "title";
public static final String JSON_CONTENT = "content";
public static final String JSON_FAVORITE = "favorite";
public static final String JSON_CATEGORY = "category";
public static final String JSON_ETAG = "etag";
public static final String JSON_MODIFIED = "modified";
private static final String application_json = "application/json";
private String url = "";
private String username = "";
private String password = "";
public NotesClient(String url, String username, String password) {
this.url = url;
this.username = username;
this.password = password;
}
public NotesResponse getNotes(CustomCertManager ccm, long lastModified, String lastETag) throws JSONException, IOException {
String url = "notes";
if (lastModified > 0) {
url += "?pruneBefore=" + lastModified;
}
return new NotesResponse(requestServer(ccm, url, METHOD_GET, null, lastETag));
}
/**
* Fetches a Note by ID from Server
*
* @param id long - ID of the wanted note
* @return Requested Note
* @throws JSONException
* @throws IOException
*/
@SuppressWarnings("unused")
public NoteResponse getNoteById(CustomCertManager ccm, long id) throws JSONException, IOException {
return new NoteResponse(requestServer(ccm, "notes/" + id, METHOD_GET, null, null));
}
private NoteResponse putNote(CustomCertManager ccm, CloudNote note, String path, String method) throws JSONException, IOException {
JSONObject paramObject = new JSONObject();
paramObject.accumulate(JSON_CONTENT, note.getContent());
paramObject.accumulate(JSON_MODIFIED, note.getModified().getTimeInMillis() / 1000);
paramObject.accumulate(JSON_FAVORITE, note.isFavorite());
paramObject.accumulate(JSON_CATEGORY, note.getCategory());
return new NoteResponse(requestServer(ccm, path, method, paramObject, null));
}
/**
* Creates a Note on the Server
*
* @param note {@link CloudNote} - the new Note
* @return Created Note including generated Title, ID and lastModified-Date
* @throws JSONException
* @throws IOException
*/
public NoteResponse createNote(CustomCertManager ccm, CloudNote note) throws JSONException, IOException {
return putNote(ccm, note, "notes", METHOD_POST);
}
public NoteResponse editNote(CustomCertManager ccm, CloudNote note) throws JSONException, IOException {
return putNote(ccm, note, "notes/" + note.getRemoteId(), METHOD_PUT);
}
public void deleteNote(CustomCertManager ccm, long noteId) throws IOException {
this.requestServer(ccm, "notes/" + noteId, METHOD_DELETE, null, null);
}
/**
* Request-Method for POST, PUT with or without JSON-Object-Parameter
*
* @param target Filepath to the wanted function
* @param method GET, POST, DELETE or PUT
* @param params JSON Object which shall be transferred to the server.
* @return Body of answer
* @throws MalformedURLException
* @throws IOException
*/
private ResponseData requestServer(CustomCertManager ccm, String target, String method, JSONObject params, String lastETag)
throws IOException {
StringBuffer result = new StringBuffer();
// setup connection
String targetURL = url + "index.php/apps/notes/api/v0.2/" + target;
HttpURLConnection con = SupportUtil.getHttpURLConnection(ccm, targetURL);
con.setRequestMethod(method);
con.setRequestProperty(
"Authorization",
"Basic " + Base64.encodeToString((username + ":" + password).getBytes(), Base64.NO_WRAP));
// https://github.com/square/retrofit/issues/805#issuecomment-93426183
con.setRequestProperty( "Connection", "Close");
con.setRequestProperty("User-Agent", "nextcloud-notes/" + BuildConfig.VERSION_NAME + " (Android)");
if (lastETag != null && METHOD_GET.equals(method)) {
con.setRequestProperty("If-None-Match", lastETag);
}
con.setConnectTimeout(10 * 1000); // 10 seconds
Log.d(getClass().getSimpleName(), method + " " + targetURL);
// send request data (optional)
byte[] paramData = null;
if (params != null) {
paramData = params.toString().getBytes();
Log.d(getClass().getSimpleName(), "Params: " + params);
con.setFixedLengthStreamingMode(paramData.length);
con.setRequestProperty("Content-Type", application_json);
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write(paramData);
os.flush();
os.close();
}
// read response data
int responseCode = con.getResponseCode();
Log.d(getClass().getSimpleName(), "HTTP response code: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_NOT_MODIFIED) {
throw new ServerResponse.NotModifiedException();
}
BufferedReader rd = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
result.append(line);
}
// create response object
String etag = con.getHeaderField("ETag");
long lastModified = con.getHeaderFieldDate("Last-Modified", 0) / 1000;
Log.i(getClass().getSimpleName(), "Result length: " + result.length() + (paramData == null ? "" : "; Request length: " + paramData.length));
Log.d(getClass().getSimpleName(), "ETag: " + etag + "; Last-Modified: " + lastModified + " (" + con.getHeaderField("Last-Modified") + ")");
// return these header fields since they should only be saved after successful processing the result!
return new ResponseData(result.toString(), etag, lastModified);
}
}

View file

@ -1,147 +0,0 @@
package it.niedermann.owncloud.notes.util;
import androidx.annotation.StringRes;
import android.util.Base64;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import at.bitfire.cert4android.CustomCertManager;
import it.niedermann.owncloud.notes.R;
/**
* Utils for Validation etc
* Created by stefan on 25.09.15.
*/
public class NotesClientUtil {
public enum LoginStatus {
OK(0),
AUTH_FAILED(R.string.error_username_password_invalid),
CONNECTION_FAILED(R.string.error_io),
NO_NETWORK(R.string.error_no_network),
JSON_FAILED(R.string.error_json),
SERVER_FAILED(R.string.error_server);
@StringRes
public final int str;
LoginStatus(@StringRes int str) {
this.str = str;
}
}
/**
* Checks if the given url String starts with http:// or https://
*
* @param url String
* @return true, if the given String is only http
*/
public static boolean isHttp(String url) {
return url != null && url.length() > 4 && url.startsWith("http") && url.charAt(4) != 's';
}
/**
* Strips the api part from the path of a given url, handles trailing slash and missing protocol
*
* @param url String
* @return formatted URL
*/
public static String formatURL(String url) {
if (!url.endsWith("/")) {
url += "/";
}
if (!url.startsWith("http://") && !url.startsWith("https://")) {
url = "https://" + url;
}
String[] replacements = new String[]{"notes/", "v0.2/", "api/", "notes/", "apps/", "index.php/"};
for (String replacement : replacements) {
if (url.endsWith(replacement)) {
url = url.substring(0, url.length() - replacement.length());
}
}
return url;
}
/**
* @param url String
* @param username String
* @param password String
* @return Username and Password are a valid Login-Combination for the given URL.
*/
public static LoginStatus isValidLogin(CustomCertManager ccm, String url, String username, String password) {
try {
String targetURL = url + "index.php/apps/notes/api/v0.2/notes";
HttpURLConnection con = SupportUtil.getHttpURLConnection(ccm, targetURL);
con.setRequestMethod("GET");
con.setRequestProperty(
"Authorization",
"Basic "
+ new String(Base64.encode((username + ":"
+ password).getBytes(), Base64.NO_WRAP)));
con.setConnectTimeout(10 * 1000); // 10 seconds
con.connect();
Log.v(NotesClientUtil.class.getSimpleName(), "Establishing connection to server");
if (con.getResponseCode() == 200) {
Log.v(NotesClientUtil.class.getSimpleName(), "" + con.getResponseMessage());
StringBuilder result = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
result.append(line);
}
Log.v(NotesClientUtil.class.getSimpleName(), result.toString());
new JSONArray(result.toString());
return LoginStatus.OK;
} else if (con.getResponseCode() >= 401 && con.getResponseCode() <= 403) {
return LoginStatus.AUTH_FAILED;
} else {
return LoginStatus.SERVER_FAILED;
}
} catch (MalformedURLException | SocketTimeoutException e) {
Log.e(NotesClientUtil.class.getSimpleName(), "Exception", e);
return LoginStatus.CONNECTION_FAILED;
} catch (IOException e) {
Log.e(NotesClientUtil.class.getSimpleName(), "Exception", e);
return LoginStatus.CONNECTION_FAILED;
} catch (JSONException e) {
Log.e(NotesClientUtil.class.getSimpleName(), "Exception", e);
return LoginStatus.JSON_FAILED;
}
}
/**
* Pings a server and checks if there is a installed ownCloud instance
*
* @param url String URL to server
* @return true if there is a installed instance, false if not
*/
public static boolean isValidURL(CustomCertManager ccm, String url) {
StringBuilder result = new StringBuilder();
try {
HttpURLConnection con = SupportUtil.getHttpURLConnection(ccm, url + "status.php");
con.setRequestMethod(NotesClient.METHOD_GET);
con.setConnectTimeout(10 * 1000); // 10 seconds
BufferedReader rd = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
result.append(line);
}
JSONObject response = new JSONObject(result.toString());
return response.getBoolean("installed");
} catch (IOException | JSONException | NullPointerException e) {
return false;
}
}
}

View file

@ -0,0 +1,39 @@
package it.niedermann.owncloud.notes.util;
import android.app.Activity;
import android.util.Log;
import androidx.annotation.NonNull;
import com.nextcloud.android.sso.AccountImporter;
import com.nextcloud.android.sso.exceptions.AndroidGetAccountsPermissionNotGranted;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotInstalledException;
import com.nextcloud.android.sso.ui.UiExceptionManager;
public class SSOUtil {
private static final String TAG = SSOUtil.class.getSimpleName();
private SSOUtil() {
}
/**
* Opens a dialog which allows the user to pick a Nextcloud account (which previously has to be configured in the files app).
* Also allows to configure a new Nextcloud account in the files app and directly import it.
*
* @param activity should implement AccountImporter.onActivityResult
*/
public static void askForNewAccount(@NonNull Activity activity) {
try {
AccountImporter.pickNewAccount(activity);
} catch (NextcloudFilesAppNotInstalledException e1) {
UiExceptionManager.showDialogForException(activity, e1);
Log.w(TAG, "=============================================================");
Log.w(TAG, "Nextcloud app is not installed. Cannot choose account");
e1.printStackTrace();
} catch (AndroidGetAccountsPermissionNotGranted e2) {
AccountImporter.requestAndroidAccountPermissionsAndPickAccount(activity);
}
}
}

View file

@ -4,22 +4,19 @@ import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.List; import java.util.List;
import it.niedermann.owncloud.notes.model.CloudNote; import it.niedermann.owncloud.notes.model.CloudNote;
import it.niedermann.owncloud.notes.persistence.NotesClient;
/** /**
* Provides entity classes for handling server responses with a single note ({@link NoteResponse}) or a list of notes ({@link NotesResponse}). * Provides entity classes for handling server responses with a single note ({@link NoteResponse}) or a list of notes ({@link NotesResponse}).
*/ */
public class ServerResponse { public class ServerResponse {
public static class NotModifiedException extends IOException {
}
public static class NoteResponse extends ServerResponse { public static class NoteResponse extends ServerResponse {
public NoteResponse(NotesClient.ResponseData response) { public NoteResponse(NotesClient.ResponseData response) {
super(response); super(response);
@ -49,12 +46,12 @@ public class ServerResponse {
private final NotesClient.ResponseData response; private final NotesClient.ResponseData response;
public ServerResponse(NotesClient.ResponseData response) { ServerResponse(NotesClient.ResponseData response) {
this.response = response; this.response = response;
} }
protected String getContent() { protected String getContent() {
return response.getContent(); return response == null ? null : response.getContent();
} }
public String getETag() { public String getETag() {
@ -65,7 +62,7 @@ public class ServerResponse {
return response.getLastModified(); return response.getLastModified();
} }
protected CloudNote getNoteFromJSON(JSONObject json) throws JSONException { CloudNote getNoteFromJSON(JSONObject json) throws JSONException {
long id = 0; long id = 0;
String title = ""; String title = "";
String content = ""; String content = "";

View file

@ -82,7 +82,7 @@ public class StyleCallback implements ActionMode.Callback {
break; break;
case R.id.link: case R.id.link:
boolean textToFormatIsLink = TextUtils.indexOf(editText.getText().subSequence(start, end), "http") == 0; boolean textToFormatIsLink = TextUtils.indexOf(editText.getText().subSequence(start, end), "http") == 0;
if(textToFormatIsLink) { if (textToFormatIsLink) {
ssb.insert(end, ")"); ssb.insert(end, ")");
ssb.insert(start, "[]("); ssb.insert(start, "[](");
} else { } else {
@ -92,12 +92,25 @@ public class StyleCallback implements ActionMode.Callback {
end++; end++;
ssb.setSpan(new StyleSpan(Typeface.NORMAL), start, end, 1); ssb.setSpan(new StyleSpan(Typeface.NORMAL), start, end, 1);
editText.setText(ssb); editText.setText(ssb);
if(textToFormatIsLink) { if (textToFormatIsLink) {
editText.setSelection(start + 1); editText.setSelection(start + 1);
} else { } else {
editText.setSelection(end + 2); // after <end>]( editText.setSelection(end + 2); // after <end>](
} }
return true; return true;
case android.R.id.cut: {
// https://github.com/stefan-niedermann/nextcloud-notes/issues/604
// https://github.com/stefan-niedermann/nextcloud-notes/issues/477
try {
editText.onTextContextMenuItem(item.getItemId());
return true;
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
editText.setSelection(0, 0);
editText.clearFocus();
return true;
}
}
} }
return false; return false;
} }

View file

@ -1,29 +1,12 @@
package it.niedermann.owncloud.notes.util; package it.niedermann.owncloud.notes.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build; import android.os.Build;
import android.preference.PreferenceManager;
import androidx.annotation.WorkerThread;
import android.text.Html; import android.text.Html;
import android.text.Spanned; import android.text.Spanned;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.widget.TextView; import android.widget.TextView;
import java.io.IOException; import androidx.annotation.NonNull;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import at.bitfire.cert4android.CustomCertManager;
import it.niedermann.owncloud.notes.R;
/** /**
* Some helper functionality in alike the Android support library. * Some helper functionality in alike the Android support library.
@ -31,20 +14,8 @@ import it.niedermann.owncloud.notes.R;
*/ */
public class SupportUtil { public class SupportUtil {
/** private SupportUtil() {
* Creates a {@link Spanned} from a HTML string on all SDK versions.
*
* @param source Source string with HTML markup
* @return Spannable for using in a {@link TextView}
* @see Html#fromHtml(String)
* @see Html#fromHtml(String, int)
*/
public static Spanned fromHtml(String source) {
if (Build.VERSION.SDK_INT >= 24) {
return Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY);
} else {
return Html.fromHtml(source);
}
} }
/** /**
@ -54,45 +25,24 @@ public class SupportUtil {
* @param stringId The string resource containing HTML tags (escaped by <code>&lt;</code>) * @param stringId The string resource containing HTML tags (escaped by <code>&lt;</code>)
* @param formatArgs Arguments for the string resource. * @param formatArgs Arguments for the string resource.
*/ */
public static void setHtml(TextView view, int stringId, Object... formatArgs) { public static void setHtml(@NonNull TextView view, int stringId, Object... formatArgs) {
view.setText(SupportUtil.fromHtml(view.getResources().getString(stringId, formatArgs))); view.setText(SupportUtil.fromHtml(view.getResources().getString(stringId, formatArgs)));
view.setMovementMethod(LinkMovementMethod.getInstance()); view.setMovementMethod(LinkMovementMethod.getInstance());
} }
/** /**
* Create a new {@link HttpURLConnection} for strUrl. * Creates a {@link Spanned} from a HTML string on all SDK versions.
* If protocol equals https, then install CustomCertManager in {@link SSLContext}.
* *
* @param ccm * @param source Source string with HTML markup
* @param strUrl * @return Spannable for using in a {@link TextView}
* @return HttpURLConnection with custom trust manager * @see Html#fromHtml(String)
* @throws MalformedURLException * @see Html#fromHtml(String, int)
* @throws IOException
*/ */
public static HttpURLConnection getHttpURLConnection(CustomCertManager ccm, String strUrl) throws MalformedURLException, IOException { private static Spanned fromHtml(String source) {
URL url = new URL(strUrl); if (Build.VERSION.SDK_INT >= 24) {
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); return Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY);
if (ccm != null && url.getProtocol().equals("https")) { } else {
HttpsURLConnection httpsCon = (HttpsURLConnection) httpCon; return Html.fromHtml(source);
httpsCon.setHostnameVerifier(ccm.hostnameVerifier(httpsCon.getHostnameVerifier()));
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{ccm}, null);
httpsCon.setSSLSocketFactory(sslContext.getSocketFactory());
} catch (NoSuchAlgorithmException e) {
Log.e(SupportUtil.class.getSimpleName(), "Exception", e);
// ignore, use default TrustManager
} catch (KeyManagementException e) {
Log.e(SupportUtil.class.getSimpleName(), "Exception", e);
// ignore, use default TrustManager
}
} }
return httpCon;
}
@WorkerThread
public static CustomCertManager getCertManager(Context ctx) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
return new CustomCertManager(ctx, preferences.getBoolean(ctx.getString(R.string.pref_key_trust_system_certs), true));
} }
} }

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?><!-- Selector is used for Background Colors in List Items -->
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/bg_highlighted">
<!-- :selected -->
<item>
<selector>
<item android:state_selected="true">
<color android:color="@color/bg_highlighted" />
</item>
<item android:state_activated="true">
<color android:color="@color/bg_highlighted" />
</item>
<item>
<color android:color="@color/bg_normal" />
</item>
</selector>
</item>
</ripple>

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View file

@ -1,5 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp" <vector android:autoMirrored="true" android:height="24dp"
android:tint="#757575" android:viewportHeight="24.0" android:tint="#FFFFFF" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/> <path android:fillColor="#FFFFFFFF" android:pathData="M7,10l5,5 5,-5z"/>
</vector> </vector>

View file

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF757575"
android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z"/>
</vector>

View file

@ -1,5 +1,5 @@
<vector android:height="24dp" android:tint="#757575" <vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0" android:tint="#757575" android:viewportHeight="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF757575" android:pathData="M20,2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM18,7h-3v5.5c0,1.38 -1.12,2.5 -2.5,2.5S10,13.88 10,12.5s1.12,-2.5 2.5,-2.5c0.57,0 1.08,0.19 1.5,0.51L14,5h4v2zM4,6L2,6v14c0,1.1 0.9,2 2,2h14v-2L4,20L4,6z"/> <path android:fillColor="#FF757575" android:pathData="M20,2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM18,7h-3v5.5c0,1.38 -1.12,2.5 -2.5,2.5S10,13.88 10,12.5s1.12,-2.5 2.5,-2.5c0.57,0 1.08,0.19 1.5,0.51L14,5h4v2zM4,6L2,6v14c0,1.1 0.9,2 2,2h14v-2L4,20L4,6z"/>
</vector> </vector>

View file

@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:tint="#757575" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF757575" android:pathData="M18,3v2h-2L16,3L8,3v2L6,5L6,3L4,3v18h2v-2h2v2h8v-2h2v2h2L20,3h-2zM8,17L6,17v-2h2v2zM8,13L6,13v-2h2v2zM8,9L6,9L6,7h2v2zM18,17h-2v-2h2v2zM18,13h-2v-2h2v2zM18,9h-2L16,7h2v2z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:tint="#757575" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M15,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM6,10L6,7L4,7v3L1,10v2h3v3h2v-3h3v-2L6,10zM15,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

View file

@ -1,5 +0,0 @@
<vector android:autoMirrored="true" android:height="24dp"
android:tint="#666666" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M1,9l2,2c4.97,-4.97 13.03,-4.97 18,0l2,-2C16.93,2.93 7.08,2.93 1,9zM9,17l3,3 3,-3c-1.65,-1.66 -4.34,-1.66 -6,0zM5,13l2,2c2.76,-2.76 7.24,-2.76 10,0l2,-2C15.14,9.14 8.87,9.14 5,13z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:tint="#757575" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF757575" android:pathData="M20,6h-4L16,4c0,-1.11 -0.89,-2 -2,-2h-4c-1.11,0 -2,0.89 -2,2v2L4,6c-1.11,0 -1.99,0.89 -1.99,2L2,19c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2zM14,6h-4L10,4h4v2z"/>
</vector>

View file

@ -3,4 +3,4 @@
<!-- :selected --> <!-- :selected -->
<item android:drawable="@color/bg_highlighted" android:state_selected="true" /> <item android:drawable="@color/bg_highlighted" android:state_selected="true" />
<item android:drawable="@color/bg_normal" /> <item android:drawable="@color/bg_normal" />
</selector> </selector>

View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/editContentContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinatorLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -19,21 +20,66 @@
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:elevation="4dp" /> app:elevation="4dp" />
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:tools="http://schemas.android.com/tools" <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/swiperefreshlayout" android:id="@+id/swiperefreshlayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/bg_normal" android:background="@color/bg_normal"
tools:context="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity" tools:context="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity">
tools:ignore="MergeRootFrame"> <FrameLayout
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent">
android:background="@color/bg_highlighted"
android:scrollbars="vertical" />
<RelativeLayout
android:id="@+id/empty_content_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="1.5"
android:scaleY="1.5"
android:layout_above="@id/empty_content_view_title"
android:layout_centerHorizontal="true"
android:layout_marginBottom="10dp"
android:contentDescription="@null"
android:src="@drawable/ic_launcher_foreground"
android:tint="@color/fg_default_high" />
<TextView
android:id="@+id/empty_content_view_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/no_notes_yet"
android:textSize="26sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/empty_content_view_title"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:text="@string/no_notes_yet_description" />
</RelativeLayout>
<ProgressBar
android:id="@+id/progress_circular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/bg_highlighted"
android:scrollbars="vertical"
tools:listitem="@layout/fragment_notes_list_note_item"/>
</FrameLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</LinearLayout> </LinearLayout>
@ -41,7 +87,7 @@
<com.google.android.material.floatingactionbutton.FloatingActionButton <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_create" android:id="@+id/fab_create"
style="@style/fab" style="@style/fab"
android:src="@drawable/ic_add_white_24dp" app:srcCompat="@drawable/ic_add_white_24dp"
android:title="@string/action_create" android:title="@string/action_create"
app:backgroundTint="@color/primary" app:backgroundTint="@color/primary"
app:rippleColor="@color/primary_dark" /> app:rippleColor="@color/primary_dark" />

View file

@ -1,75 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/settings_url_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp">
<EditText
android:id="@+id/settings_url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/settings_url"
android:inputType="textUri"
android:textColor="@color/fg_default" />
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:id="@+id/settings_url_warn_http"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:background="@color/bg_attention"
android:padding="8dp"
android:text="@string/settings_url_warn_http"
android:textColor="@color/fg_contrast"
android:visibility="gone" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/settings_username_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/settings_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/settings_username"
android:inputType="text"
android:textColor="@color/fg_default" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/settings_password_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:passwordToggleEnabled="true">
<EditText
android:id="@+id/settings_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/settings_password"
android:inputType="textPassword"
android:textColor="@color/fg_default" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/settings_submit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10pt"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:text="@string/settings_submit"/>
</LinearLayout>

View file

@ -1,10 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawerLayout" android:id="@+id/drawerLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fitsSystemWindows="true"> android:fitsSystemWindows="true"
tools:openDrawer="left">
<include <include
layout="@layout/activity_notes_list_view" layout="@layout/activity_notes_list_view"
@ -12,13 +14,13 @@
android:layout_height="match_parent" /> android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView <com.google.android.material.navigation.NavigationView
android:id="@+id/navigationView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="start" android:layout_gravity="start"
android:fitsSystemWindows="true"> android:fitsSystemWindows="true">
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -27,68 +29,109 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <RelativeLayout
android:id="@+id/header_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/colorPrimary" android:background="?attr/colorPrimary"
android:padding="10dp" android:theme="@style/ThemeOverlay.AppCompat.Dark">
android:theme="@style/ThemeOverlay.AppCompat.Dark"
android:orientation="horizontal"
android:gravity="bottom">
<ImageView <androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="164dp"
android:paddingTop="24dp" android:contentDescription="@null"
android:scaleType="centerCrop"
app:srcCompat="@drawable/background" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/current_account_image"
android:layout_width="@dimen/avatar_size"
android:layout_height="@dimen/avatar_size"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:src="@mipmap/ic_launcher" android:layout_marginStart="@dimen/header_padding"
android:contentDescription="@string/app_name" /> android:layout_marginLeft="@dimen/header_padding"
android:layout_marginTop="46dp"
android:contentDescription="@string/app_name"
app:srcCompat="@mipmap/ic_launcher" />
<TextView
<androidx.appcompat.widget.LinearLayoutCompat android:id="@+id/app_name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_below="@id/current_account_image"
android:paddingLeft="12dp" android:layout_marginTop="6dp"
android:paddingStart="12dp" android:layout_marginStart="@dimen/header_padding"
android:paddingTop="24dp" android:layout_marginLeft="@dimen/header_padding"
android:orientation="vertical"> android:layout_marginEnd="@dimen/header_padding"
<TextView android:layout_marginRight="@dimen/header_padding"
android:layout_width="match_parent" android:ellipsize="end"
android:layout_height="wrap_content" android:shadowColor="@color/fg_default"
android:text="@string/app_name" android:shadowDx="0.5"
android:textAppearance="@style/TextAppearance.AppCompat.Title" /> android:shadowDy="0"
android:shadowRadius="2"
android:text="@string/app_name_long"
android:textColor="@android:color/white"
android:textSize="14sp"
android:textStyle="bold" />
<TextView <TextView
android:id="@+id/account" android:id="@+id/account"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"
</androidx.appcompat.widget.LinearLayoutCompat> android:layout_below="@+id/app_name"
</LinearLayout> android:layout_marginStart="@dimen/header_padding"
android:layout_marginLeft="@dimen/header_padding"
android:layout_marginEnd="@dimen/header_padding"
android:layout_marginRight="@dimen/header_padding"
android:ellipsize="end"
android:maxLines="1"
android:shadowColor="@color/fg_default"
android:shadowDx="0.5"
android:shadowDy="0"
android:shadowRadius="2"
android:textColor="@android:color/white"
android:textSize="12sp"
tools:text="user@nextcloud.example.com"/>
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_arrow_drop_down_white_24dp"
android:layout_alignEnd="@+id/account"
android:layout_alignRight="@+id/account"
android:layout_alignBottom="@+id/account" />
</RelativeLayout>
<LinearLayout
android:id="@+id/accountNavigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/navigationList" android:id="@+id/navigationList"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="start"
android:paddingTop="8dp" android:paddingTop="8dp"
android:paddingBottom="8dp" android:paddingBottom="8dp"
app:layoutManager="LinearLayoutManager" /> app:layoutManager="LinearLayoutManager" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/separator" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/navigationMenu" android:id="@+id/navigationMenu"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="start"
android:paddingTop="8dp" android:paddingTop="8dp"
android:paddingBottom="8dp" android:paddingBottom="8dp"
app:layoutManager="LinearLayoutManager" /> app:layoutManager="LinearLayoutManager" />
</LinearLayout>
<LinearLayout
android:id="@+id/accountChooser"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:orientation="vertical"
android:visibility="gone"/>
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>

View file

@ -10,7 +10,6 @@
android:padding="@dimen/activity_horizontal_margin"> android:padding="@dimen/activity_horizontal_margin">
<TextView <TextView
android:id="@+id/about_source_title"
style="?android:attr/listSeparatorTextViewStyle" style="?android:attr/listSeparatorTextViewStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -25,7 +24,6 @@
android:text="@string/about_source" /> android:text="@string/about_source" />
<TextView <TextView
android:id="@+id/about_issues_title"
style="?android:attr/listSeparatorTextViewStyle" style="?android:attr/listSeparatorTextViewStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -40,7 +38,6 @@
android:text="@string/about_issues" /> android:text="@string/about_issues" />
<TextView <TextView
android:id="@+id/about_translate_title"
style="?android:attr/listSeparatorTextViewStyle" style="?android:attr/listSeparatorTextViewStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View file

@ -10,7 +10,6 @@
android:padding="@dimen/activity_horizontal_margin"> android:padding="@dimen/activity_horizontal_margin">
<TextView xmlns:android="http://schemas.android.com/apk/res/android" <TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/textView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -23,7 +22,6 @@
android:textSize="26sp" /> android:textSize="26sp" />
<TextView <TextView
android:id="@+id/about_version_title"
style="?android:attr/listSeparatorTextViewStyle" style="?android:attr/listSeparatorTextViewStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -38,7 +36,6 @@
android:text="@string/about_version" /> android:text="@string/about_version" />
<TextView <TextView
android:id="@+id/about_maintainer_title"
style="?android:attr/listSeparatorTextViewStyle" style="?android:attr/listSeparatorTextViewStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -53,14 +50,12 @@
android:text="@string/about_maintainer" /> android:text="@string/about_maintainer" />
<TextView <TextView
android:id="@+id/about_developers_title"
style="?android:attr/listSeparatorTextViewStyle" style="?android:attr/listSeparatorTextViewStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/about_developers_title" /> android:text="@string/about_developers_title" />
<TextView <TextView
android:id="@+id/about_developers"
style="?android:attr/editTextPreferenceStyle" style="?android:attr/editTextPreferenceStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -68,7 +63,6 @@
android:text="@string/about_developers" /> android:text="@string/about_developers" />
<TextView <TextView
android:id="@+id/about_translators_title"
style="?android:attr/listSeparatorTextViewStyle" style="?android:attr/listSeparatorTextViewStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -83,14 +77,12 @@
android:text="@string/about_translators_transifex" /> android:text="@string/about_translators_transifex" />
<TextView <TextView
android:id="@+id/about_testers_title"
style="?android:attr/listSeparatorTextViewStyle" style="?android:attr/listSeparatorTextViewStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/about_testers_title" /> android:text="@string/about_testers_title" />
<TextView <TextView
android:id="@+id/about_testers"
style="?android:attr/editTextPreferenceStyle" style="?android:attr/editTextPreferenceStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View file

@ -10,14 +10,12 @@
android:padding="@dimen/activity_horizontal_margin"> android:padding="@dimen/activity_horizontal_margin">
<TextView <TextView
android:id="@+id/about_app_license_title"
style="?android:attr/listSeparatorTextViewStyle" style="?android:attr/listSeparatorTextViewStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/about_app_license_title" /> android:text="@string/about_app_license_title" />
<TextView <TextView
android:id="@+id/about_app_license"
style="?android:attr/editTextPreferenceStyle" style="?android:attr/editTextPreferenceStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -31,7 +29,6 @@
android:text="@string/about_app_license_button" /> android:text="@string/about_app_license_button" />
<TextView <TextView
android:id="@+id/about_icons_disclaimer_title"
style="?android:attr/listSeparatorTextViewStyle" style="?android:attr/listSeparatorTextViewStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View file

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/noteSwipeFrame" android:id="@+id/noteSwipeFrame"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -13,17 +15,17 @@
android:layout_marginLeft="@dimen/button_padding" android:layout_marginLeft="@dimen/button_padding"
android:layout_marginStart="@dimen/button_padding" android:layout_marginStart="@dimen/button_padding"
android:contentDescription="@string/menu_favorite" android:contentDescription="@string/menu_favorite"
android:src="@drawable/ic_star_white_24dp" /> app:srcCompat="@drawable/ic_star_white_24dp" />
<ImageView <ImageView
android:id="@+id/noteDeleteRight" android:id="@+id/noteDeleteRight"
android:layout_width="32dp" android:layout_width="32dp"
android:layout_height="32dp" android:layout_height="32dp"
android:layout_gravity="right|end|center_vertical" android:layout_gravity="end|center_vertical"
android:layout_marginEnd="@dimen/button_padding" android:layout_marginEnd="@dimen/button_padding"
android:layout_marginRight="@dimen/button_padding" android:layout_marginRight="@dimen/button_padding"
android:contentDescription="@string/menu_delete" android:contentDescription="@string/menu_delete"
android:src="@drawable/ic_delete_white_32dp" /> app:srcCompat="@drawable/ic_delete_white_32dp" />
<androidx.appcompat.widget.LinearLayoutCompat <androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/noteSwipeable" android:id="@+id/noteSwipeable"
@ -36,16 +38,15 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent"> android:layout_height="match_parent">
<ImageView <ImageView
android:id="@+id/noteFavorite" android:id="@+id/noteFavorite"
android:contentDescription="@string/menu_favorite" android:contentDescription="@string/menu_favorite"
android:padding="16dp" android:padding="16dp"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" /> android:layout_height="match_parent"
tools:src="@drawable/ic_star_yellow_24dp"/>
<androidx.appcompat.widget.AppCompatImageView
<ImageView
android:id="@+id/noteStatus" android:id="@+id/noteStatus"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -54,7 +55,7 @@
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:layout_gravity="center_vertical|end" android:layout_gravity="center_vertical|end"
android:baseline="14dp" android:baseline="14dp"
android:src="@drawable/ic_sync_blue_18dp" /> app:srcCompat="@drawable/ic_sync_blue_18dp" />
</FrameLayout> </FrameLayout>
@ -64,14 +65,15 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="16dp" android:paddingTop="16dp"
android:paddingRight="16dp" android:paddingRight="16dp"
android:paddingEnd="16dp"
android:paddingLeft="0dp"
android:paddingStart="0dp"
android:paddingBottom="16dp" android:paddingBottom="16dp"
android:orientation="vertical" android:orientation="vertical">
android:background="@drawable/list_item_background_selector">
<androidx.appcompat.widget.LinearLayoutCompat <androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:background="@drawable/list_item_background_selector">
<TextView <TextView
android:id="@+id/noteTitle" android:id="@+id/noteTitle"
@ -80,15 +82,14 @@
android:singleLine="true" android:singleLine="true"
android:layout_weight="1" android:layout_weight="1"
android:textColor="@drawable/list_item_color_selector" android:textColor="@drawable/list_item_color_selector"
android:textSize="@dimen/primary_font_size" /> android:textSize="@dimen/primary_font_size"
tools:text="The title of the note"/>
</androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat <androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:background="@drawable/list_item_background_selector">
<TextView <TextView
android:id="@+id/noteExcerpt" android:id="@+id/noteExcerpt"
@ -102,7 +103,8 @@
android:paddingTop="1dp" android:paddingTop="1dp"
android:layout_weight="1" android:layout_weight="1"
android:textColor="@drawable/list_item_color_selector_low" android:textColor="@drawable/list_item_color_selector_low"
android:textSize="@dimen/secondary_font_size" /> android:textSize="@dimen/secondary_font_size"
tools:text="This is the content of the first line."/>
<TextView <TextView
android:id="@+id/noteCategory" android:id="@+id/noteCategory"
@ -120,7 +122,8 @@
android:layout_marginLeft="8dp" android:layout_marginLeft="8dp"
android:singleLine="true" android:singleLine="true"
android:textColor="@drawable/list_item_color_selector" android:textColor="@drawable/list_item_color_selector"
android:textSize="@dimen/secondary_font_size" /> android:textSize="@dimen/secondary_font_size"
tools:text="My fancy category"/>
</androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat>
@ -128,6 +131,7 @@
<ImageView <ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1px" android:layout_height="1px"
android:contentDescription="@null"
android:src="@color/separator" /> android:src="@color/separator" />
</FrameLayout> </FrameLayout>

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sectionItem"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">

View file

@ -0,0 +1,49 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="?attr/selectableItemBackground"
android:paddingLeft="6dp"
android:paddingStart="6dp"
android:paddingRight="8dp"
android:paddingEnd="8dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/accountItemAvatar"
android:layout_width="44dp"
android:layout_height="44dp"
android:padding="10dp"
android:scaleType="center"
android:focusable="false"
app:srcCompat="@drawable/ic_account_circle_grey_24dp"
android:contentDescription="@null" />
<TextView
android:id="@+id/accountItemLabel"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="64dp"
android:layout_marginStart="64dp"
android:layout_marginRight="64dp"
android:layout_marginEnd="64dp"
android:ellipsize="middle"
android:singleLine="true"
android:textColor="@color/fg_default"
android:textAppearance="@style/NavigationItem"
tools:hint="Username"/>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/delete"
android:layout_width="44dp"
android:layout_height="44dp"
android:padding="10dp"
android:scaleType="center"
android:focusable="false"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
app:srcCompat="@drawable/ic_delete_grey600_24dp"
android:contentDescription="@string/menu_delete" />
</RelativeLayout>

View file

@ -1,19 +1,22 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:paddingLeft="6dp" android:paddingLeft="6dp"
android:paddingStart="6dp" android:paddingStart="6dp"
android:paddingRight="8dp" android:paddingRight="8dp"
android:paddingEnd="8dp"> android:paddingEnd="8dp">
<ImageView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/navigationItemIcon" android:id="@+id/navigationItemIcon"
android:layout_width="44dp" android:layout_width="44dp"
android:layout_height="44dp" android:layout_height="44dp"
android:padding="10dp" android:padding="10dp"
android:scaleType="center" android:scaleType="center"
android:focusable="false" android:focusable="false"
android:src="@drawable/ic_folder_grey600_24dp" /> app:srcCompat="@drawable/ic_folder_grey600_24dp"
android:contentDescription="@null" />
<TextView <TextView
android:id="@+id/navigationItemCount" android:id="@+id/navigationItemCount"
@ -23,7 +26,8 @@
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:padding="8dp" android:padding="8dp"
android:textAppearance="@style/NavigationItem" /> android:textAppearance="@style/NavigationItem"
tools:text="37"/>
<TextView <TextView
android:id="@+id/navigationItemLabel" android:id="@+id/navigationItemLabel"
@ -36,6 +40,7 @@
android:layout_marginStart="64dp" android:layout_marginStart="64dp"
android:ellipsize="end" android:ellipsize="end"
android:lines="1" android:lines="1"
android:textAppearance="@style/NavigationItem" /> android:textAppearance="@style/NavigationItem"
tools:text="Category 1" />
</RelativeLayout> </RelativeLayout>

View file

@ -9,7 +9,6 @@
android:focusable="true"> android:focusable="true">
<ImageView <ImageView
android:id="@+id/ivCreateNoteBadge"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal" android:layout_gravity="center_vertical|center_horizontal"

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/widget_note_list_entry" android:id="@+id/widget_note_list_entry"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -16,7 +17,7 @@
android:paddingLeft="@dimen/widget_note_list_inner_padding" android:paddingLeft="@dimen/widget_note_list_inner_padding"
android:paddingEnd="@dimen/widget_note_list_outer_padding" android:paddingEnd="@dimen/widget_note_list_outer_padding"
android:paddingRight="@dimen/widget_note_list_outer_padding" android:paddingRight="@dimen/widget_note_list_outer_padding"
android:src="@drawable/ic_star_yellow_24dp" app:srcCompat="@drawable/ic_star_yellow_24dp"
android:contentDescription="@string/widget_entry_fav_contentDescription" /> android:contentDescription="@string/widget_entry_fav_contentDescription" />
<TextView <TextView

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/widget_note_list_entry_dark" android:id="@+id/widget_note_list_entry_dark"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -16,7 +17,7 @@
android:paddingLeft="@dimen/widget_note_list_inner_padding" android:paddingLeft="@dimen/widget_note_list_inner_padding"
android:paddingEnd="@dimen/widget_note_list_outer_padding" android:paddingEnd="@dimen/widget_note_list_outer_padding"
android:paddingRight="@dimen/widget_note_list_outer_padding" android:paddingRight="@dimen/widget_note_list_outer_padding"
android:src="@drawable/ic_star_yellow_24dp" app:srcCompat="@drawable/ic_star_yellow_24dp"
android:contentDescription="@string/widget_entry_fav_contentDescription" /> android:contentDescription="@string/widget_entry_fav_contentDescription" />
<TextView <TextView

View file

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:background="@color/widget_background"
android:background="@color/widget_background"> android:orientation="vertical">
<!-- Widget header --> <!-- Widget header -->
<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:id="@+id/widget_note_list_hdr"
android:layout_height="@dimen/widget_note_list_header_height" android:layout_height="@dimen/widget_note_list_header_height"
android:background="@color/primary" android:background="@color/primary"
android:padding="@dimen/widget_note_list_hdr_padding"> android:padding="@dimen/widget_note_list_hdr_padding">
@ -36,11 +36,14 @@
android:textSize="18sp" android:textSize="18sp"
android:layout_toRightOf="@id/widget_note_header_icon" android:layout_toRightOf="@id/widget_note_header_icon"
android:layout_toEndOf="@id/widget_note_header_icon" android:layout_toEndOf="@id/widget_note_header_icon"
android:layout_toLeftOf="@id/widget_note_list_create_icon"
android:layout_toStartOf="@id/widget_note_list_create_icon"
android:gravity="center_vertical" android:gravity="center_vertical"
android:paddingStart="@dimen/widget_note_list_outer_padding" android:paddingStart="@dimen/widget_note_list_outer_padding"
android:paddingEnd="@dimen/widget_note_list_inner_padding" android:paddingEnd="@dimen/widget_note_list_inner_padding"
android:paddingLeft="@dimen/widget_note_list_outer_padding" android:paddingLeft="@dimen/widget_note_list_outer_padding"
android:paddingRight="@dimen/widget_note_list_inner_padding" /> android:paddingRight="@dimen/widget_note_list_inner_padding"
tools:text="@string/app_name"/>
<ImageView <ImageView
android:id="@+id/widget_note_list_create_icon" android:id="@+id/widget_note_list_create_icon"
@ -63,7 +66,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/fg_default" /> android:textColor="@color/fg_default"
tools:listitem="@layout/widget_entry"/>
<TextView <TextView
android:id="@+id/widget_note_list_placeholder_tv" android:id="@+id/widget_note_list_placeholder_tv"
@ -71,6 +75,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center" android:gravity="center"
android:text="@string/widget_note_list_placeholder" android:text="@string/widget_note_list_placeholder"
android:textColor="@color/fg_default_high" /> android:textColor="@color/fg_default_high"
tools:visibility="gone"/>
</LinearLayout> </LinearLayout>

View file

@ -2,13 +2,13 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:orientation="vertical"
android:background="@color/widget_background_dark_theme"> android:background="@color/widget_background_dark_theme">
<!-- Widget header --> <!-- Widget header -->
<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:id="@+id/widget_note_list_hdr_dark"
android:layout_height="@dimen/widget_note_list_header_height" android:layout_height="@dimen/widget_note_list_header_height"
android:background="@color/primary" android:background="@color/primary"
android:padding="@dimen/widget_note_list_hdr_padding"> android:padding="@dimen/widget_note_list_hdr_padding">
@ -36,11 +36,14 @@
android:textSize="18sp" android:textSize="18sp"
android:layout_toRightOf="@id/widget_note_header_icon_dark" android:layout_toRightOf="@id/widget_note_header_icon_dark"
android:layout_toEndOf="@id/widget_note_header_icon_dark" android:layout_toEndOf="@id/widget_note_header_icon_dark"
android:layout_toStartOf="@id/widget_note_list_create_icon_dark"
android:layout_toLeftOf="@id/widget_note_list_create_icon_dark"
android:gravity="center_vertical" android:gravity="center_vertical"
android:paddingStart="@dimen/widget_note_list_outer_padding" android:paddingStart="@dimen/widget_note_list_outer_padding"
android:paddingEnd="@dimen/widget_note_list_inner_padding" android:paddingEnd="@dimen/widget_note_list_inner_padding"
android:paddingLeft="@dimen/widget_note_list_outer_padding" android:paddingLeft="@dimen/widget_note_list_outer_padding"
android:paddingRight="@dimen/widget_note_list_inner_padding" /> android:paddingRight="@dimen/widget_note_list_inner_padding"
tools:text="@string/app_name"/>
<ImageView <ImageView
android:id="@+id/widget_note_list_create_icon_dark" android:id="@+id/widget_note_list_create_icon_dark"
@ -62,9 +65,10 @@
android:id="@+id/note_list_widget_lv_dark" android:id="@+id/note_list_widget_lv_dark"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:divider="@color/fg_default_low_dark_theme"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/fg_default_dark_theme" android:textColor="@color/fg_default_dark_theme"
android:divider="@color/fg_default_low_dark_theme"/> tools:listitem="@layout/widget_entry_dark" />
<TextView <TextView
android:id="@+id/widget_note_list_placeholder_tv_dark" android:id="@+id/widget_note_list_placeholder_tv_dark"
@ -72,6 +76,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center" android:gravity="center"
android:text="@string/widget_note_list_placeholder" android:text="@string/widget_note_list_placeholder"
android:textColor="@color/fg_default_dark_theme" /> android:textColor="@color/fg_default_dark_theme"
tools:visibility="gone" />
</LinearLayout> </LinearLayout>

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widget_single_note"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/widget_background"> android:background="@color/widget_background">

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widget_single_note_dark"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/widget_background_dark_theme"> android:background="@color/widget_background_dark_theme">

View file

@ -2,37 +2,30 @@
<resources> <resources>
<string name="app_name">Notes</string> <string name="app_name">Notes</string>
<string name="no_notes">No notes yet</string>
<string name="label_all_notes">All notes</string> <string name="label_all_notes">All notes</string>
<string name="label_favorites">Favourites</string> <string name="label_favorites">Favourites</string>
<string name="action_create">New note</string> <string name="action_create">New note</string>
<string name="action_settings">Settings</string> <string name="action_settings">Settings</string>
<string name="action_trashbin">Deleted notes</string> <string name="action_trashbin">Deleted notes</string>
<string name="action_search">Search</string> <string name="action_search">Search</string>
<string name="action_create_save">Save</string>
<string name="simple_cancel">Cancel</string> <string name="simple_cancel">Cancel</string>
<string name="simple_edit">Edit</string> <string name="simple_edit">Edit</string>
<string name="action_edit_save">Save</string> <string name="action_edit_save">Save</string>
<string name="action_edit_saving">Saving &#8230;</string>
<string name="action_edit_saved">Saved</string>
<string name="simple_about">About</string> <string name="simple_about">About</string>
<string name="simple_bold">Bold</string> <string name="simple_bold">Bold</string>
<string name="simple_link">Link</string> <string name="simple_link">Link</string>
<string name="simple_italic">Italic</string> <string name="simple_italic">Italic</string>
<string name="action_select_note">Select note</string>
<string name="action_note_deleted">Note deleted</string> <string name="action_note_deleted">Note deleted</string>
<string name="action_note_restored">Note restored</string> <string name="action_note_restored">Note restored</string>
<string name="action_undo">Undo</string> <string name="action_undo">Undo</string>
<string name="action_drawer_open">open navigation</string> <string name="action_drawer_open">open navigation</string>
<string name="action_drawer_close">close navigation</string> <string name="action_drawer_close">close navigation</string>
<string name="action_recent">Recent</string>
<string name="action_uncategorized">Uncategorised</string> <string name="action_uncategorized">Uncategorised</string>
<string name="menu_delete">Delete</string> <string name="menu_delete">Delete</string>
<string name="menu_change_category">Category</string> <string name="menu_change_category">Category</string>
<string name="menu_favorite">Favourite</string> <string name="menu_favorite">Favourite</string>
<string name="menu_preview">Preview</string> <string name="menu_preview">Preview</string>
<string name="menu_share">Share</string> <string name="menu_share">Share</string>
<string name="menu_about">About</string>
<string name="change_category_title">Choose a category</string> <string name="change_category_title">Choose a category</string>
@ -40,52 +33,21 @@
<string name="listview_updated_yesterday">Yesterday</string> <string name="listview_updated_yesterday">Yesterday</string>
<string name="listview_updated_this_week">This week</string> <string name="listview_updated_this_week">This week</string>
<string name="listview_updated_this_month">This month</string> <string name="listview_updated_this_month">This month</string>
<string name="listview_updated_earlier">Earlier</string>
<!-- Settings --> <!-- Settings -->
<string name="settings_server_settings">Account</string>
<string name="settings_url">Server address</string>
<string name="settings_url_check_description">Shows whether the address can be pinged.</string>
<string name="settings_url_warn_http">WARNING: \"http\" is unsafe. Please use \"https\".</string>
<string name="settings_username">Username</string>
<string name="settings_password">Password</string>
<string name="settings_password_unchanged">Password (not changed)</string>
<string name="settings_password_check_description">Displays whether the credentials are correct.</string>
<string name="settings_submit">Connect</string>
<string name="settings_submitting">Connecting &#8230;</string>
<string name="settings_note_mode">Display mode for notes</string> <string name="settings_note_mode">Display mode for notes</string>
<string name="settings_theme_title">Dark theme</string> <string name="settings_theme_title">Dark theme</string>
<string name="settings_font_title">Monospace font</string> <string name="settings_font_title">Monospace font</string>
<string name="settings_font_size">Font size</string>
<string name="settings_wifi_only">Sync only on Wi-Fi</string> <string name="settings_wifi_only">Sync only on Wi-Fi</string>
<string name="settings_cert_category">Manage certificates</string>
<string name="settings_cert_trust_system">Trust system certificates</string>
<string name="settings_cert_trust_system_on">System and user-added CAs will be trusted (recommended)</string>
<string name="settings_cert_trust_system_off">System and user-added CAs won\'t be trusted</string>
<string name="settings_cert_reset">Reset (un)trusted certificates</string>
<string name="settings_cert_reset_summary">Resets trust of all custom certificates</string>
<string name="settings_cert_reset_toast">All custom certificates have been cleared</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notes - Connection security</string>
<string name="trust_certificate_unknown_certificate_found">Notes has encountered an unknown certificate. Do you want to trust it?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Connecting</string>
<string name="network_connected">Connected</string>
<string name="network_disconnected">No network available</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Synchronisation failed: %1$s</string> <string name="error_sync">Synchronisation failed: %1$s</string>
<string name="error_invalid_login">Invalid login: %1$s</string>
<string name="error_json">is the Notes app activated on the server?</string> <string name="error_json">is the Notes app activated on the server?</string>
<string name="error_io">server connection is broken</string>
<string name="error_no_network">no network connection</string> <string name="error_no_network">no network connection</string>
<string name="error_server">URL/Server has errors</string>
<string name="error_url_malformed">Wrong server address</string>
<string name="error_username_password_invalid">Wrong username or password</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Settings</string>
<!-- About --> <!-- About -->
<string name="about_version_title">Version</string> <string name="about_version_title">Version</string>
@ -126,7 +88,16 @@
<string name="shortcut_create_long">Create a new note</string> <string name="shortcut_create_long">Create a new note</string>
<string name="pref_value_theme_light">Light</string> <string name="pref_value_theme_light">Light</string>
<string name="pref_value_theme_dark">Dark</string> <string name="pref_value_font_normal">Normal</string>
<string name="simple_error">Error</string>
<string name="simple_close">Close</string>
<string name="simple_copy">Copy</string>
<string name="copied_to_clipboard">Copied to clipboard</string>
<string name="add_account">Add account</string>
<string name="category_music">Music</string>
<string name="category_movies">Movies</string>
<string name="category_work">Work</string>
<string name="no_notes_yet">No notes yet</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Open in edit mode</item> <item>Open in edit mode</item>
@ -134,6 +105,12 @@
<item>Remember my last selection</item> <item>Remember my last selection</item>
</string-array> </string-array>
<!-- Array: font size -->
<string-array name="fontSize_entries">
<item>Small</item>
<item>Large</item>
</string-array>
<!-- Plurals --> <!-- Plurals -->
<plurals name="ab_selected"> <plurals name="ab_selected">
<item quantity="one">%d selected</item> <item quantity="one">%d selected</item>

View file

@ -2,72 +2,37 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="action_select_note">Seleccionar nota</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="listview_updated_today">Hoy</string> <string name="listview_updated_today">Hoy</string>
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions --> <!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>

View file

@ -2,57 +2,31 @@
<resources> <resources>
<string name="app_name">Бележки</string> <string name="app_name">Бележки</string>
<string name="no_notes">Няма открити бележки</string>
<string name="action_create">Нова бележка</string> <string name="action_create">Нова бележка</string>
<string name="action_settings">Настройки</string> <string name="action_settings">Настройки</string>
<string name="action_create_save">Запис</string>
<string name="simple_cancel">Отказ</string> <string name="simple_cancel">Отказ</string>
<string name="simple_edit">Редакция</string> <string name="simple_edit">Редакция</string>
<string name="action_edit_save">Запис</string> <string name="action_edit_save">Запис</string>
<string name="action_edit_saving">Записване &#8230;</string>
<string name="action_edit_saved">Запазено</string>
<string name="action_edit_cancel">Отказ</string>
<string name="simple_about">Относно</string> <string name="simple_about">Относно</string>
<string name="action_select_note">Избор на бележка</string>
<string name="action_note_deleted">Бележката е изтрита</string> <string name="action_note_deleted">Бележката е изтрита</string>
<string name="action_note_restored">Бележката е възстановена</string> <string name="action_note_restored">Бележката е възстановена</string>
<string name="action_undo">Отмяна</string> <string name="action_undo">Отмяна</string>
<string name="menu_delete">Изтриване</string> <string name="menu_delete">Изтриване</string>
<string name="menu_copy">Копиране</string>
<string name="menu_edit">Редакция</string>
<string name="menu_cancel">Отказ</string>
<string name="menu_favorite">Любим</string> <string name="menu_favorite">Любим</string>
<string name="menu_preview">Преглед</string> <string name="menu_preview">Преглед</string>
<string name="menu_share">Споделяне</string> <string name="menu_share">Споделяне</string>
<string name="menu_about">Относно</string>
<string name="copy">Копиране</string>
<string name="listview_updated_today">Днес</string> <string name="listview_updated_today">Днес</string>
<string name="listview_updated_yesterday">Вчера</string> <string name="listview_updated_yesterday">Вчера</string>
<string name="listview_updated_this_week">Тази седмица</string> <string name="listview_updated_this_week">Тази седмица</string>
<string name="listview_updated_this_month">Този месец</string> <string name="listview_updated_this_month">Този месец</string>
<string name="settings_url">Адрес на сървъра</string>
<string name="settings_username">Потребител</string>
<string name="settings_password">Парола</string>
<string name="settings_submit">Свързване</string>
<string name="settings_submitting">Свързване &#8230;</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Свързване</string>
<string name="network_connected">Свързан</string>
<string name="network_disconnected">Няма налична мрежа</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Синхронизацията е неуспешна: %1$s</string> <string name="error_sync">Синхронизацията е неуспешна: %1$s</string>
<string name="error_invalid_login">Невалиден вход: %1$s</string>
<string name="error_io">връзката със сървъра е прекъснала</string>
<string name="error_no_network">няма връзка с интернет</string> <string name="error_no_network">няма връзка с интернет</string>
<string name="error_server">URL/Сървъра съдържа грешки</string>
<string name="error_url_malformed">Грешен адрес на сървъра</string>
<string name="error_username_password_invalid">Грешно потребителско име или парола</string>
<!-- Snackbar Actions --> <!-- Snackbar Actions -->
<string name="snackbar_settings">Настройки</string>
<!-- About --> <!-- About -->
<string name="about_version_title">Версия</string> <string name="about_version_title">Версия</string>
@ -72,7 +46,6 @@
<string name="about_contribution_tab_title">Принос</string> <string name="about_contribution_tab_title">Принос</string>
<string name="about_license_tab_title">Лиценз</string> <string name="about_license_tab_title">Лиценз</string>
<string name="widget_all_notes_title">Всички бележки</string>
<string name="widget_single_note_title">Единична бележка</string> <string name="widget_single_note_title">Единична бележка</string>
<!-- Plurals --> <!-- Plurals -->

View file

@ -2,91 +2,56 @@
<resources> <resources>
<string name="app_name">Notes</string> <string name="app_name">Notes</string>
<string name="no_notes">Encara no hi ha notes</string> <string name="app_name_long">Notes de Nextcloud</string>
<string name="label_all_notes">Totes les notes</string> <string name="label_all_notes">Totes les notes</string>
<string name="label_favorites">Preferides</string> <string name="label_favorites">Preferides</string>
<string name="action_create">Crea una nota</string> <string name="action_create">Crea una nota</string>
<string name="action_settings">Paràmetres</string> <string name="action_settings">Paràmetres</string>
<string name="action_trashbin">Notes suprimides</string> <string name="action_trashbin">Notes suprimides</string>
<string name="action_search">Cerca</string> <string name="action_search">Cerca</string>
<string name="action_create_save">Desa</string>
<string name="simple_cancel">Cancel·la</string> <string name="simple_cancel">Cancel·la</string>
<string name="simple_edit">Edita</string> <string name="simple_edit">Edita</string>
<string name="action_edit_save">Desa</string> <string name="action_edit_save">Desa</string>
<string name="action_edit_saving">S\'està desant &#8230;</string>
<string name="action_edit_saved">S\'ha desat</string>
<string name="simple_about">Quant a</string> <string name="simple_about">Quant a</string>
<string name="simple_bold">Negreta</string> <string name="simple_bold">Negreta</string>
<string name="simple_link">Enllaç</string> <string name="simple_link">Enllaç</string>
<string name="simple_italic">Cursiva</string> <string name="simple_italic">Cursiva</string>
<string name="action_select_note">Selecciona una nota</string>
<string name="action_note_deleted">S\'ha suprimit la nota</string> <string name="action_note_deleted">S\'ha suprimit la nota</string>
<string name="action_note_restored">S\'ha restaurat la nota</string> <string name="action_note_restored">S\'ha restaurat la nota</string>
<string name="action_undo">Desfés</string> <string name="action_undo">Desfés</string>
<string name="action_drawer_open">obre la navegació</string> <string name="action_drawer_open">obre la navegació</string>
<string name="action_drawer_close">tanca la navegació</string> <string name="action_drawer_close">tanca la navegació</string>
<string name="action_recent">Recents</string>
<string name="action_uncategorized">Sense categoria</string> <string name="action_uncategorized">Sense categoria</string>
<string name="menu_delete">Suprimeix</string> <string name="menu_delete">Suprimeix</string>
<string name="menu_change_category">Categoria</string> <string name="menu_change_category">Categoria</string>
<string name="menu_favorite">Preferida</string> <string name="menu_favorite">Preferida</string>
<string name="menu_preview">Previsualitza</string> <string name="menu_preview">Previsualitza</string>
<string name="menu_share">Comparteix</string> <string name="menu_share">Comparteix</string>
<string name="menu_about">Quant a</string>
<string name="change_category_title">Tria una categoria</string> <string name="change_category_title">Tria una categoria</string>
<string name="listview_updated_today">Avui</string> <string name="listview_updated_today">Avui</string>
<string name="listview_updated_yesterday">Ahir</string> <string name="listview_updated_yesterday">Ahir</string>
<string name="listview_updated_this_week">Aquesta setmana</string> <string name="listview_updated_this_week">Aquesta setmana</string>
<string name="listview_updated_last_week">La setmana passada</string>
<string name="listview_updated_this_month">Aquest mes</string> <string name="listview_updated_this_month">Aquest mes</string>
<string name="listview_updated_earlier">Abans</string> <string name="listview_updated_last_month">El mes passat</string>
<!-- Settings --> <!-- Settings -->
<string name="settings_server_settings">Compte</string>
<string name="settings_url">Adreça del servidor</string>
<string name="settings_url_check_description">Mostra si es pot fer ping a l\'adreça.</string>
<string name="settings_url_warn_http">ATENCIÓ: \"http\" és insegur. Si us plau feu servir \"https\".</string>
<string name="settings_username">Nom d\'usuari</string>
<string name="settings_password">Contrasenya</string>
<string name="settings_password_unchanged">Contrasenya (sense canvis)</string>
<string name="settings_password_check_description">Mostra si les credencials són correctes.</string>
<string name="settings_submit">Connecta</string>
<string name="settings_submitting">S\'està connectant &#8230;</string>
<string name="settings_note_mode">Mode de visualització per les notes</string> <string name="settings_note_mode">Mode de visualització per les notes</string>
<string name="settings_theme_title">Tema fosc</string> <string name="settings_theme_title">Tema fosc</string>
<string name="settings_font_title">Tipus de lletra de mida fixa</string> <string name="settings_font_title">Tipus de lletra de mida fixa</string>
<string name="settings_font_size">Mida de la lletra</string> <string name="settings_font_size">Mida de la lletra</string>
<string name="settings_wifi_only">Sincronitza només per Wi-Fi</string> <string name="settings_wifi_only">Sincronitza només per Wi-Fi</string>
<string name="settings_cert_category">Gestiona els certificats</string>
<string name="settings_cert_trust_system">Confia en els certificats del sistema</string>
<string name="settings_cert_trust_system_on">Es confiarà en els CAs afegits pel sistema i per l\'usuari (recomanat)</string>
<string name="settings_cert_trust_system_off">No es confiarà en els CAs afegits pel sistema ni per l\'usuari</string>
<string name="settings_cert_reset">Restableix els certificats confiats i desconfiats</string>
<string name="settings_cert_reset_summary">Restableix la confiança de tots els certificats personalitzats</string>
<string name="settings_cert_reset_toast">Tots els certificats personalitzats han estat suprimits</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notes - Seguretat de la connexió</string>
<string name="trust_certificate_unknown_certificate_found">Notes ha trobat un certificat desconegut. Voleu confiar-hi?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">S\'està connectant</string>
<string name="network_connected">S\'ha connectat</string>
<string name="network_disconnected">No hi ha cap xarxa disponible</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Ha fallat la sincronització: %1$s</string> <string name="error_sync">Ha fallat la sincronització: %1$s</string>
<string name="error_invalid_login">Inici de sessió no vàlid: %1$s</string>
<string name="error_json">l\'aplicació Notes està activada al servidor?</string> <string name="error_json">l\'aplicació Notes està activada al servidor?</string>
<string name="error_io">s\'ha trencat la connexió amb el servidor</string>
<string name="error_no_network">no hi ha connexió a la xarxa</string> <string name="error_no_network">no hi ha connexió a la xarxa</string>
<string name="error_server">L\'URL o el servidor contenen errors</string>
<string name="error_url_malformed">L\'adreça del servidor és incorrecta</string>
<string name="error_username_password_invalid">El nom d\'usuari o la contrasenya són incorrectes</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Paràmetres</string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versió</string> <string name="about_version_title">Versió</string>
@ -127,7 +92,6 @@
<string name="shortcut_create_long">Crea una nota nova</string> <string name="shortcut_create_long">Crea una nota nova</string>
<string name="pref_value_theme_light">Clar</string> <string name="pref_value_theme_light">Clar</string>
<string name="pref_value_theme_dark">Fosc</string>
<string name="pref_value_font_normal">Normal</string> <string name="pref_value_font_normal">Normal</string>
<string name="pref_value_wifi_and_mobile">Sincronitza per Wi-Fi i dades mòbils</string> <string name="pref_value_wifi_and_mobile">Sincronitza per Wi-Fi i dades mòbils</string>
<string name="simple_error">Error</string> <string name="simple_error">Error</string>
@ -137,7 +101,11 @@
<string name="copied_to_clipboard">S\'ha copiat al porta-retalls</string> <string name="copied_to_clipboard">S\'ha copiat al porta-retalls</string>
<string name="pin_to_homescreen">Fixa-ho a la pantalla d\'inici</string> <string name="pin_to_homescreen">Fixa-ho a la pantalla d\'inici</string>
<string name="note_has_been_deleted">S\'ha suprimit aquesta nota</string> <string name="note_has_been_deleted">S\'ha suprimit aquesta nota</string>
<string name="add_account">Afegeix un compte</string>
<string name="category_music">Música</string>
<string name="category_movies">Peŀlícules</string>
<string name="category_work">Feina</string>
<string name="no_notes_yet">Encara no hi ha notes</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Obre en mode d\'edició</item> <item>Obre en mode d\'edició</item>

View file

@ -2,90 +2,56 @@
<resources> <resources>
<string name="app_name">Poznámky</string> <string name="app_name">Poznámky</string>
<string name="no_notes">Zatím žádné poznámky</string> <string name="app_name_long">Nextcloud poznámky</string>
<string name="label_all_notes">Všechny poznámky</string> <string name="label_all_notes">Všechny poznámky</string>
<string name="label_favorites">Oblíbené</string> <string name="label_favorites">Oblíbené</string>
<string name="action_create">Nová poznámka</string> <string name="action_create">Nová poznámka</string>
<string name="action_settings">Nastavení</string> <string name="action_settings">Nastavení</string>
<string name="action_trashbin">Smazané poznámky</string> <string name="action_trashbin">Smazané poznámky</string>
<string name="action_search">Hledat</string> <string name="action_search">Hledat</string>
<string name="action_create_save">Uložit</string>
<string name="simple_cancel">Storno</string> <string name="simple_cancel">Storno</string>
<string name="simple_edit">Upravit</string> <string name="simple_edit">Upravit</string>
<string name="action_edit_save">Uložit</string> <string name="action_edit_save">Uložit</string>
<string name="action_edit_saving">Ukládání &#8230;</string>
<string name="action_edit_saved">Uloženo</string>
<string name="simple_about">O aplikaci</string> <string name="simple_about">O aplikaci</string>
<string name="simple_bold">Tučné</string> <string name="simple_bold">Tučné</string>
<string name="simple_link">Odkaz</string> <string name="simple_link">Odkaz</string>
<string name="simple_italic">Skloněné</string> <string name="simple_italic">Skloněné</string>
<string name="action_select_note">Vybrat poznámku</string> <string name="action_note_deleted">Poznámka smazána</string>
<string name="action_note_deleted">Poznámka byla smazána</string> <string name="action_note_restored">Poznámka obnovena</string>
<string name="action_note_restored">Poznámka byla obnovena</string>
<string name="action_undo">Zpět</string> <string name="action_undo">Zpět</string>
<string name="action_drawer_open">otevřít navigační panel</string> <string name="action_drawer_open">otevřít navigační panel</string>
<string name="action_drawer_close">zavřít navigační panel</string> <string name="action_drawer_close">zavřít navigační panel</string>
<string name="action_recent">Nedávné</string>
<string name="action_uncategorized">Nezařazeno</string> <string name="action_uncategorized">Nezařazeno</string>
<string name="menu_delete">Smazat</string> <string name="menu_delete">Smazat</string>
<string name="menu_change_category">Kategorie</string> <string name="menu_change_category">Kategorie</string>
<string name="menu_favorite">Oblíbený</string> <string name="menu_favorite">Oblíbený</string>
<string name="menu_preview">Náhled</string> <string name="menu_preview">Náhled</string>
<string name="menu_share">Sdílet</string> <string name="menu_share">Sdílet</string>
<string name="menu_about">O aplikaci</string>
<string name="change_category_title">Zvolte kategorii</string> <string name="change_category_title">Zvolte kategorii</string>
<string name="listview_updated_today">Dnes</string> <string name="listview_updated_today">Dnes</string>
<string name="listview_updated_yesterday">Včera</string> <string name="listview_updated_yesterday">Včera</string>
<string name="listview_updated_this_week">Tento týden</string> <string name="listview_updated_this_week">Tento týden</string>
<string name="listview_updated_last_week">Minulý týden</string>
<string name="listview_updated_this_month">Tento měsíc</string> <string name="listview_updated_this_month">Tento měsíc</string>
<string name="listview_updated_earlier">Dříve</string> <string name="listview_updated_last_month">Minulý měsíc</string>
<!-- Settings --> <!-- Settings -->
<string name="settings_server_settings">Účet</string>
<string name="settings_url">Adresa serveru</string>
<string name="settings_url_check_description">Značí, zda lze adresu pingnout.</string>
<string name="settings_url_warn_http">POZOR: „http„ není bezpečné. Prosím použijte „https“</string>
<string name="settings_username">Uživatelské jméno</string>
<string name="settings_password">Heslo</string>
<string name="settings_password_unchanged">Heslo (nezměněno)</string>
<string name="settings_password_check_description">Zobrazí, zda jsou pověření správná.</string>
<string name="settings_submit">Připojit</string>
<string name="settings_submitting">Připojování &#8230;</string>
<string name="settings_note_mode">Režim zobrazení pro poznámky</string> <string name="settings_note_mode">Režim zobrazení pro poznámky</string>
<string name="settings_theme_title">Tmavý motiv vzhledu</string> <string name="settings_theme_title">Tmavý motiv vzhledu</string>
<string name="settings_font_title">Písmo s pevnou šířkou</string> <string name="settings_font_title">Písmo se znaky všemi stejně širokými</string>
<string name="settings_font_size">Velikost písma</string>
<string name="settings_wifi_only">Synchronizovat pouze přes Wi-Fi</string> <string name="settings_wifi_only">Synchronizovat pouze přes Wi-Fi</string>
<string name="settings_cert_category">Spravovat certifikáty</string>
<string name="settings_cert_trust_system">Důvěřovat systémovým certifikátům</string>
<string name="settings_cert_trust_system_on">Systémové a uživatelsky přidané CA budou důvěryhodné (doporučeno)</string>
<string name="settings_cert_trust_system_off">Systémové a uživatelsky přidané CA nebudou důvěryhodné</string>
<string name="settings_cert_reset">Obnovit úložiště (ne)důvěryhodných certifikátů</string>
<string name="settings_cert_reset_summary">Obnoví výchozí nastavení důvěry vlastních certifikátů</string>
<string name="settings_cert_reset_toast">Všechny vlastní certifikáty byly odebrány</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Poznámky Zabezpečení připojení</string>
<string name="trust_certificate_unknown_certificate_found">Poznámky se setkaly s neznámým certifikátem. Chcete mu věřit?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Připojování</string>
<string name="network_connected">Připojeno</string>
<string name="network_disconnected">Síť není dostupná</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Synchronizace se nezdařila: %1$s</string> <string name="error_sync">Synchronizace se nezdařila: %1$s</string>
<string name="error_invalid_login">Neplatné přihlášení: %1$s</string> <string name="error_json">je na serveru aktivní aplikace Poznámky?</string>
<string name="error_json">je aplikace Poznámky aktivní na serveru?</string>
<string name="error_io">spojení se serverem není funkční</string>
<string name="error_no_network">žádné síťové spojení</string> <string name="error_no_network">žádné síťové spojení</string>
<string name="error_server">Chyby v URL/Serveru</string>
<string name="error_url_malformed">Chybná adresa serveru</string>
<string name="error_username_password_invalid">Chybné uživatelské jméno nebo heslo</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Nastavení</string>
<!-- About --> <!-- About -->
<string name="about_version_title">Verze</string> <string name="about_version_title">Verze</string>
@ -96,9 +62,9 @@
<string name="about_translators_transifex">Nextcloud komunita na &lt;a href=\"%1$s\">Transifex&lt;/a></string> <string name="about_translators_transifex">Nextcloud komunita na &lt;a href=\"%1$s\">Transifex&lt;/a></string>
<string name="about_testers_title">Testeři</string> <string name="about_testers_title">Testeři</string>
<string name="about_source_title">Zdrojové kódy</string> <string name="about_source_title">Zdrojové kódy</string>
<string name="about_source">Tento projekt je hostován na GitHub: &lt;a href=\"%1$s\">%1$s&lt;/a></string> <string name="about_source">Tento projekt je hostován na portálu GitHub: &lt;a href=\"%1$s\">%1$s&lt;/a></string>
<string name="about_issues_title">Problémy</string> <string name="about_issues_title">Problémy</string>
<string name="about_issues">Můžete nahlásit chyby, návrhy a požadavky na zlepšení na GitHub issue tracker: &lt;a href=\"%1$s\">%1$s&lt;/a></string> <string name="about_issues">Chyby, návrhy na zlepšení a další funkce je možné posílat prostřednictvím systému správy hlášení na portálu GitHub: &lt;a href=\"%1$s\">%1$s&lt;/a></string>
<string name="about_translate_title">Překládat</string> <string name="about_translate_title">Překládat</string>
<string name="about_translate">Připojte se k týmu na službě Transifex a pomozte nám přelkládat tuto aplikaci: &lt;a href=\"%1$s\">%1$s&lt;/a></string> <string name="about_translate">Připojte se k týmu na službě Transifex a pomozte nám přelkládat tuto aplikaci: &lt;a href=\"%1$s\">%1$s&lt;/a></string>
<string name="about_app_license_title">Licence aplikace</string> <string name="about_app_license_title">Licence aplikace</string>
@ -117,7 +83,7 @@
<string name="widget_single_note_placeholder_tv">Poznámka nenalezena</string> <string name="widget_single_note_placeholder_tv">Poznámka nenalezena</string>
<string name="widget_create_note">Vytvořit poznámku</string> <string name="widget_create_note">Vytvořit poznámku</string>
<string name="widget_not_logged_in">Abyste mohli tento widget používat, přihlaste se do aplikacie Poznámky</string> <string name="widget_not_logged_in">Abyste mohli tento widget používat, přihlaste se do aplikacie Poznámky</string>
<string name="widget_entry_fav_contentDescription">Ikonka hvězdy označí položku jako oblíbenou</string> <string name="widget_entry_fav_contentDescription">Ikonka hvězdičky označí položku jako oblíbenou</string>
<string name="widget_app_launcher_contentDescription">Spustí aplikaci</string> <string name="widget_app_launcher_contentDescription">Spustí aplikaci</string>
<string name="activity_select_single_note">Vybrat poznámku</string> <string name="activity_select_single_note">Vybrat poznámku</string>
@ -126,7 +92,6 @@
<string name="shortcut_create_long">Vytvořit novou poznámku</string> <string name="shortcut_create_long">Vytvořit novou poznámku</string>
<string name="pref_value_theme_light">Světlý</string> <string name="pref_value_theme_light">Světlý</string>
<string name="pref_value_theme_dark">Tmavé</string>
<string name="pref_value_font_normal">Normální</string> <string name="pref_value_font_normal">Normální</string>
<string name="pref_value_wifi_and_mobile">Synchronizovat přes Wi-Fi a mobilní data</string> <string name="pref_value_wifi_and_mobile">Synchronizovat přes Wi-Fi a mobilní data</string>
<string name="simple_error">Chyba</string> <string name="simple_error">Chyba</string>
@ -136,6 +101,14 @@
<string name="copied_to_clipboard">Zkopírováno do schránky</string> <string name="copied_to_clipboard">Zkopírováno do schránky</string>
<string name="pin_to_homescreen">Připnout na domovskou obrazovku</string> <string name="pin_to_homescreen">Připnout na domovskou obrazovku</string>
<string name="note_has_been_deleted">Tato poznámka byla smazána</string> <string name="note_has_been_deleted">Tato poznámka byla smazána</string>
<string name="add_account">Přidat účet</string>
<string name="category_music">Hudba</string>
<string name="category_movies">Filmy</string>
<string name="category_movie">Film</string>
<string name="category_work">Práce</string>
<string name="account_already_imported">Účet už byl naimportován</string>
<string name="no_notes_yet">Zatím žádné poznámky</string>
<string name="no_notes_yet_description">Pro vytvoření nové poznámky klepněte na + (plus)</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
@ -144,6 +117,13 @@
<item>Zapamatovat si můj poslední výběr</item> <item>Zapamatovat si můj poslední výběr</item>
</string-array> </string-array>
<!-- Array: font size -->
<string-array name="fontSize_entries">
<item>Malé</item>
<item>Střední</item>
<item>Velké</item>
</string-array>
<!-- Plurals --> <!-- Plurals -->
<plurals name="ab_selected"> <plurals name="ab_selected">
<item quantity="one">vybrán %d</item> <item quantity="one">vybrán %d</item>

View file

@ -2,54 +2,26 @@
<resources> <resources>
<string name="app_name">zápisník</string> <string name="app_name">zápisník</string>
<string name="no_notes">Zatím bez zápisků</string>
<string name="action_create">Nový zápisek</string> <string name="action_create">Nový zápisek</string>
<string name="action_settings">Nastavení</string> <string name="action_settings">Nastavení</string>
<string name="action_create_save">Uložit</string>
<string name="simple_cancel">Storno</string> <string name="simple_cancel">Storno</string>
<string name="simple_edit">Upravit</string> <string name="simple_edit">Upravit</string>
<string name="action_edit_save">Uložit</string> <string name="action_edit_save">Uložit</string>
<string name="action_edit_saving">Ukládám &#8230;</string>
<string name="action_edit_saved">Uloženo</string>
<string name="action_edit_cancel">Storno</string>
<string name="simple_about">O aplikaci</string> <string name="simple_about">O aplikaci</string>
<string name="action_select_note">Vybrat zápisek</string>
<string name="menu_delete">Smazat</string> <string name="menu_delete">Smazat</string>
<string name="menu_copy">Kopírovat</string>
<string name="menu_edit">Upravit</string>
<string name="menu_share">Sdílet</string> <string name="menu_share">Sdílet</string>
<string name="menu_about">O aplikaci</string>
<string name="copy">Kopírovat</string>
<string name="listview_updated_today">Dnes</string> <string name="listview_updated_today">Dnes</string>
<string name="listview_updated_yesterday">Včera</string> <string name="listview_updated_yesterday">Včera</string>
<string name="listview_updated_this_week">Tento týden</string> <string name="listview_updated_this_week">Tento týden</string>
<string name="listview_updated_this_month">Tento měsíc</string> <string name="listview_updated_this_month">Tento měsíc</string>
<string name="listview_updated_earlier">Dřívější</string>
<!-- Settings --> <!-- Settings -->
<string name="settings_url">Adresa serveru</string>
<string name="settings_url_check_description">Ukáže, zdali lze na server provést ping.</string>
<string name="settings_url_warn_http">POZOR: "http" není bezpečné. Použijte "https".</string>
<string name="settings_username">Přihlašovací jméno</string>
<string name="settings_password">Heslo</string>
<string name="settings_password_check_description">Ukáže, zdali jsou údaje správné.</string>
<string name="settings_submit">Připojit</string>
<string name="settings_submitting">Spojuji &#8230;</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Spojuji</string>
<string name="network_connected">Připojeno</string>
<string name="network_disconnected">Síť není k dispozici</string>
<string name="error_invalid_login">Chybný login</string>
<string name="error_json">JSON error</string> <string name="error_json">JSON error</string>
<string name="error_io">IO error</string>
<string name="error_url_malformed">Chybná adresa serveru</string>
<string name="error_username_password_invalid">Chybné jméno nebo heslo</string>
<!-- Snackbar Actions --> <!-- Snackbar Actions -->
<string name="snackbar_settings">Nastavení</string>
<!-- About --> <!-- About -->
@ -72,7 +44,6 @@
<string name="about_contribution_tab_title">Připěvatelé</string> <string name="about_contribution_tab_title">Připěvatelé</string>
<string name="about_license_tab_title">Licence</string> <string name="about_license_tab_title">Licence</string>
<string name="widget_all_notes_title">Všechny zápisky</string>
<string name="widget_single_note_title">Jeden zápisek</string> <string name="widget_single_note_title">Jeden zápisek</string>

View file

@ -2,37 +2,30 @@
<resources> <resources>
<string name="app_name">Nodiadau</string> <string name="app_name">Nodiadau</string>
<string name="no_notes">Dim nodiadau eto</string>
<string name="label_all_notes">Pob nodyn</string> <string name="label_all_notes">Pob nodyn</string>
<string name="label_favorites">Ffefrynnau</string> <string name="label_favorites">Ffefrynnau</string>
<string name="action_create">Nodyn newydd</string> <string name="action_create">Nodyn newydd</string>
<string name="action_settings">Gosodiadau</string> <string name="action_settings">Gosodiadau</string>
<string name="action_trashbin">Nodiadau wedi\'u dileu</string> <string name="action_trashbin">Nodiadau wedi\'u dileu</string>
<string name="action_search">Chwilio</string> <string name="action_search">Chwilio</string>
<string name="action_create_save">Cadw</string>
<string name="simple_cancel">Diddymu</string> <string name="simple_cancel">Diddymu</string>
<string name="simple_edit">Golygu</string> <string name="simple_edit">Golygu</string>
<string name="action_edit_save">Cadw</string> <string name="action_edit_save">Cadw</string>
<string name="action_edit_saving">Yn cadw &#8230;</string>
<string name="action_edit_saved">Wedi\'u cadw</string>
<string name="simple_about">Ynghylch</string> <string name="simple_about">Ynghylch</string>
<string name="simple_bold">Trwm</string> <string name="simple_bold">Trwm</string>
<string name="simple_link">Dolen</string> <string name="simple_link">Dolen</string>
<string name="simple_italic">Italig</string> <string name="simple_italic">Italig</string>
<string name="action_select_note">Dewis nodyn</string>
<string name="action_note_deleted">Nodyn wedi\'i ddileu</string> <string name="action_note_deleted">Nodyn wedi\'i ddileu</string>
<string name="action_note_restored">Nodyn wedi\'i adfer</string> <string name="action_note_restored">Nodyn wedi\'i adfer</string>
<string name="action_undo">Dadwneud</string> <string name="action_undo">Dadwneud</string>
<string name="action_drawer_open">agor llywio</string> <string name="action_drawer_open">agor llywio</string>
<string name="action_drawer_close">cau llywio</string> <string name="action_drawer_close">cau llywio</string>
<string name="action_recent">Diweddar</string>
<string name="action_uncategorized">Dim categori</string> <string name="action_uncategorized">Dim categori</string>
<string name="menu_delete">Dileu</string> <string name="menu_delete">Dileu</string>
<string name="menu_change_category">Categori</string> <string name="menu_change_category">Categori</string>
<string name="menu_favorite">Ffefryn</string> <string name="menu_favorite">Ffefryn</string>
<string name="menu_preview">Rhagolwg</string> <string name="menu_preview">Rhagolwg</string>
<string name="menu_share">Rhannu</string> <string name="menu_share">Rhannu</string>
<string name="menu_about">Ynghylch</string>
<string name="change_category_title">Dewis categori</string> <string name="change_category_title">Dewis categori</string>
@ -40,52 +33,20 @@
<string name="listview_updated_yesterday">Ddoe</string> <string name="listview_updated_yesterday">Ddoe</string>
<string name="listview_updated_this_week">Wythnos yma</string> <string name="listview_updated_this_week">Wythnos yma</string>
<string name="listview_updated_this_month">Mis yma</string> <string name="listview_updated_this_month">Mis yma</string>
<string name="listview_updated_earlier">Cynharach</string>
<!-- Settings --> <!-- Settings -->
<string name="settings_server_settings">Cyfrif</string>
<string name="settings_url">Cyfeiriad gweinydd</string>
<string name="settings_url_check_description">Yn dangos a oes modd pingio\'r cyfeiriad</string>
<string name="settings_url_warn_http">RHYBUDD: \"mae http\" yn anniogel. Defnyddiwch \"https\".</string>
<string name="settings_username">Enw defnyddiwr</string>
<string name="settings_password">Cyfrinair</string>
<string name="settings_password_unchanged">Cyfrinair (heb ei newid)</string>
<string name="settings_password_check_description">Yn dangos p\'un ai yw\'ch manylion yn gywir</string>
<string name="settings_submit">Cysylltu</string>
<string name="settings_submitting">Cysylltu i &#8230;</string>
<string name="settings_note_mode">Modd arddangos nodiadau</string> <string name="settings_note_mode">Modd arddangos nodiadau</string>
<string name="settings_theme_title">Thema tywyll</string> <string name="settings_theme_title">Thema tywyll</string>
<string name="settings_font_title">Font monofwlch</string> <string name="settings_font_title">Font monofwlch</string>
<string name="settings_wifi_only">Cysoni dros Wi-Fi yn unig</string> <string name="settings_wifi_only">Cysoni dros Wi-Fi yn unig</string>
<string name="settings_cert_category">Rheoli tystysgrifau</string>
<string name="settings_cert_trust_system">Tysytysgrfiau\'r system ymddiriedaeth</string>
<string name="settings_cert_trust_system_on">CA\'r system a\'r rhai ychwanegwyd gan y defnyddiwr yn gymeradwy (argymell)</string>
<string name="settings_cert_trust_system_off">CA\'r system a\'r rhai ychwanegwyd gan y defnyddiwr ddim yn gymeradwy</string>
<string name="settings_cert_reset">Ailosod tystysgrifau cymeradwy/anghymeradwy</string>
<string name="settings_cert_reset_summary">Ailosod ymddiriedaeth pob tytysgrif gyfaddas</string>
<string name="settings_cert_reset_toast">Mae\'r holl dystysgrifau cyfaddas wedi eu clirio</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Nodiadau - Diogelwch cysylltiad</string>
<string name="trust_certificate_unknown_certificate_found">Mae Nodiadau wedi canfod tystysgrif anhysbys. Ydych chi\'n ymddiried ynddi?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Yn cysylltu</string>
<string name="network_connected">Wedi cysylltu</string>
<string name="network_disconnected">Dim rhwydwaith ar gael</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Methodd y cydweddiad: %1$s</string> <string name="error_sync">Methodd y cydweddiad: %1$s</string>
<string name="error_invalid_login">Mewngofnod annilys: %1$s</string>
<string name="error_json">A yw\'r ap Nodiadau yn weithredol ar y gweinydd?</string> <string name="error_json">A yw\'r ap Nodiadau yn weithredol ar y gweinydd?</string>
<string name="error_io">mae cysylltiad y gweinydd wedi torri</string>
<string name="error_no_network">dim cysylltiad rthwydwaith</string> <string name="error_no_network">dim cysylltiad rthwydwaith</string>
<string name="error_server">Mae gan URL/gweinydd wallau</string>
<string name="error_url_malformed">Cyfeiriad gweinydd anghywir</string>
<string name="error_username_password_invalid">Enw defnyddiwr neu gyfrinair anghywir</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Gosodiadau</string>
<!-- About --> <!-- About -->
<string name="about_version_title">Fersiwn</string> <string name="about_version_title">Fersiwn</string>
@ -126,9 +87,13 @@
<string name="shortcut_create_long">Creu nodyn newydd</string> <string name="shortcut_create_long">Creu nodyn newydd</string>
<string name="pref_value_theme_light">Golau</string> <string name="pref_value_theme_light">Golau</string>
<string name="pref_value_theme_dark">Tywyll</string>
<string name="pref_value_font_normal">Arferol</string> <string name="pref_value_font_normal">Arferol</string>
<string name="pref_value_wifi_and_mobile">Cysoni dros Wi-Fi a data symudol</string> <string name="pref_value_wifi_and_mobile">Cysoni dros Wi-Fi a data symudol</string>
<string name="simple_error">Gwall</string>
<string name="simple_close">Cau</string>
<string name="simple_copy">Copïo</string>
<string name="category_work">Gwaith</string>
<string name="no_notes_yet">Dim nodiadau eto</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Agor yn y modd golygu</item> <item>Agor yn y modd golygu</item>

View file

@ -2,37 +2,30 @@
<resources> <resources>
<string name="app_name">Noter</string> <string name="app_name">Noter</string>
<string name="no_notes">Ingen noter endnu</string>
<string name="label_all_notes">Alle noter</string> <string name="label_all_notes">Alle noter</string>
<string name="label_favorites">Foretrukne</string> <string name="label_favorites">Foretrukne</string>
<string name="action_create">Ny note</string> <string name="action_create">Ny note</string>
<string name="action_settings">Indstillinger</string> <string name="action_settings">Indstillinger</string>
<string name="action_trashbin">Slettede noter</string> <string name="action_trashbin">Slettede noter</string>
<string name="action_search">Søg</string> <string name="action_search">Søg</string>
<string name="action_create_save">Gem</string>
<string name="simple_cancel">Annuller</string> <string name="simple_cancel">Annuller</string>
<string name="simple_edit">Rediger</string> <string name="simple_edit">Rediger</string>
<string name="action_edit_save">Gem</string> <string name="action_edit_save">Gem</string>
<string name="action_edit_saving">Gemmer &#8230;</string>
<string name="action_edit_saved">Gemt</string>
<string name="simple_about">Om</string> <string name="simple_about">Om</string>
<string name="simple_bold">Fed</string> <string name="simple_bold">Fed</string>
<string name="simple_link">Link</string> <string name="simple_link">Link</string>
<string name="simple_italic">Kursiv</string> <string name="simple_italic">Kursiv</string>
<string name="action_select_note">Vælg note</string>
<string name="action_note_deleted">Note slettet</string> <string name="action_note_deleted">Note slettet</string>
<string name="action_note_restored">Note gendannet</string> <string name="action_note_restored">Note gendannet</string>
<string name="action_undo">Fortryd</string> <string name="action_undo">Fortryd</string>
<string name="action_drawer_open">åbnn navigation</string> <string name="action_drawer_open">åbnn navigation</string>
<string name="action_drawer_close">Luk navigation</string> <string name="action_drawer_close">Luk navigation</string>
<string name="action_recent">Seneste</string>
<string name="action_uncategorized">Ikke kategoriseret</string> <string name="action_uncategorized">Ikke kategoriseret</string>
<string name="menu_delete">Slet</string> <string name="menu_delete">Slet</string>
<string name="menu_change_category">Katergori</string> <string name="menu_change_category">Katergori</string>
<string name="menu_favorite">Foretrukken</string> <string name="menu_favorite">Foretrukken</string>
<string name="menu_preview">Vis eksempel</string> <string name="menu_preview">Vis eksempel</string>
<string name="menu_share">Del</string> <string name="menu_share">Del</string>
<string name="menu_about">Om</string>
<string name="change_category_title">Vælg en kategori</string> <string name="change_category_title">Vælg en kategori</string>
@ -40,53 +33,21 @@
<string name="listview_updated_yesterday">I går</string> <string name="listview_updated_yesterday">I går</string>
<string name="listview_updated_this_week">Denne uge</string> <string name="listview_updated_this_week">Denne uge</string>
<string name="listview_updated_this_month">Denne måned</string> <string name="listview_updated_this_month">Denne måned</string>
<string name="listview_updated_earlier">Tidligere</string>
<!-- Settings --> <!-- Settings -->
<string name="settings_server_settings">Konto</string>
<string name="settings_url">Server adresse</string>
<string name="settings_url_check_description">Viser hvorvidt adressen kan blive pinget.</string>
<string name="settings_url_warn_http">Advarsel: \"http\" er ikke sikker, benyt venligst \"https\".</string>
<string name="settings_username">Brugernavn</string>
<string name="settings_password">Adgangskode</string>
<string name="settings_password_unchanged">Password (uændret)</string>
<string name="settings_password_check_description">Viser hvorvidt brugeroplysningerne er korrekte.</string>
<string name="settings_submit">Tilslut</string>
<string name="settings_submitting">Tilslutter &#8230;</string>
<string name="settings_note_mode">Visningstilstand for noter</string> <string name="settings_note_mode">Visningstilstand for noter</string>
<string name="settings_theme_title">Mørk tema</string> <string name="settings_theme_title">Mørk tema</string>
<string name="settings_font_title">Monospace font</string> <string name="settings_font_title">Monospace font</string>
<string name="settings_font_size">Skriftstørrelse</string> <string name="settings_font_size">Skriftstørrelse</string>
<string name="settings_wifi_only">Synk kun på Wi-Fi</string> <string name="settings_wifi_only">Synk kun på Wi-Fi</string>
<string name="settings_cert_category">Håndter certifikater</string>
<string name="settings_cert_trust_system">Stol på systemcertifikater</string>
<string name="settings_cert_trust_system_on">System og bruger tilføjede CA\'er stoles der på (anbefalet)</string>
<string name="settings_cert_trust_system_off">System og bruger tilføjede CA\'er stoles der ikke på</string>
<string name="settings_cert_reset">Nulstil (ikke)betroede certifikater</string>
<string name="settings_cert_reset_summary">Nulstiller alle brugerdefinerede certifikater</string>
<string name="settings_cert_reset_toast">Alle brugerdefinerede certifikater er fjernet</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Noter - forbindelsessikkerhed</string>
<string name="trust_certificate_unknown_certificate_found">Noter er stødt på et ukendt certifikat. Stoler du på det?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Tilslutter</string>
<string name="network_connected">Tilsluttet</string>
<string name="network_disconnected">Intet netværk tilgængeligt</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Synkronisering fejlede: %1$s</string> <string name="error_sync">Synkronisering fejlede: %1$s</string>
<string name="error_invalid_login">Ugyldigt login: %1$s</string>
<string name="error_json">er Notes appen aktiveret på serveren?</string> <string name="error_json">er Notes appen aktiveret på serveren?</string>
<string name="error_io">serverforbindelsen er ødelagt</string>
<string name="error_no_network">ingen netværksforbindelse</string> <string name="error_no_network">ingen netværksforbindelse</string>
<string name="error_server">URL/Server har fejl</string>
<string name="error_url_malformed">Forkert serveradresse</string>
<string name="error_username_password_invalid">Forkert brugernavn eller adgangskode</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Indstillinger</string>
<!-- About --> <!-- About -->
<string name="about_version_title">Version</string> <string name="about_version_title">Version</string>
@ -127,7 +88,6 @@
<string name="shortcut_create_long">Opret en ny note</string> <string name="shortcut_create_long">Opret en ny note</string>
<string name="pref_value_theme_light">Lys</string> <string name="pref_value_theme_light">Lys</string>
<string name="pref_value_theme_dark">Mørk</string>
<string name="pref_value_font_normal">Normal</string> <string name="pref_value_font_normal">Normal</string>
<string name="pref_value_wifi_and_mobile">Synk på Wi-Fi og mobil data</string> <string name="pref_value_wifi_and_mobile">Synk på Wi-Fi og mobil data</string>
<string name="simple_error">Fejl</string> <string name="simple_error">Fejl</string>
@ -137,7 +97,11 @@
<string name="copied_to_clipboard">Kopieret til udklipsholder</string> <string name="copied_to_clipboard">Kopieret til udklipsholder</string>
<string name="pin_to_homescreen">Fastgør til hjemmeskærm</string> <string name="pin_to_homescreen">Fastgør til hjemmeskærm</string>
<string name="note_has_been_deleted">Denne note er blevet slettet</string> <string name="note_has_been_deleted">Denne note er blevet slettet</string>
<string name="add_account">Tilføj konto</string>
<string name="category_music">Musik</string>
<string name="category_movies">Film</string>
<string name="category_work">Arbejde</string>
<string name="no_notes_yet">Ingen noter endnu</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Åbn i redigeringstilstand</item> <item>Åbn i redigeringstilstand</item>

View file

@ -2,91 +2,56 @@
<resources> <resources>
<string name="app_name">Notizen</string> <string name="app_name">Notizen</string>
<string name="no_notes">Noch keine Notizen vorhanden</string> <string name="app_name_long">Nextcloud Notizen</string>
<string name="label_all_notes">Alle Notizen</string> <string name="label_all_notes">Alle Notizen</string>
<string name="label_favorites">Favoriten</string> <string name="label_favorites">Favoriten</string>
<string name="action_create">Neue Notiz</string> <string name="action_create">Neue Notiz</string>
<string name="action_settings">Einstellungen</string> <string name="action_settings">Einstellungen</string>
<string name="action_trashbin">Gelöschte Notizen</string> <string name="action_trashbin">Gelöschte Notizen</string>
<string name="action_search">Suche</string> <string name="action_search">Suche</string>
<string name="action_create_save">Speichern</string>
<string name="simple_cancel">Abbrechen</string> <string name="simple_cancel">Abbrechen</string>
<string name="simple_edit">Bearbeiten</string> <string name="simple_edit">Bearbeiten</string>
<string name="action_edit_save">Speichern</string> <string name="action_edit_save">Speichern</string>
<string name="action_edit_saving">Speichern&#8230;</string>
<string name="action_edit_saved">Gespeichert</string>
<string name="simple_about">Über</string> <string name="simple_about">Über</string>
<string name="simple_bold">Fett</string> <string name="simple_bold">Fett</string>
<string name="simple_link">Link</string> <string name="simple_link">Link</string>
<string name="simple_italic">Kursiv</string> <string name="simple_italic">Kursiv</string>
<string name="action_select_note">Notiz auswählen</string>
<string name="action_note_deleted">Notiz gelöscht</string> <string name="action_note_deleted">Notiz gelöscht</string>
<string name="action_note_restored">Notiz wiederhergestellt</string> <string name="action_note_restored">Notiz wiederhergestellt</string>
<string name="action_undo">Rückgängig</string> <string name="action_undo">Rückgängig</string>
<string name="action_drawer_open">Navigation öffnen</string> <string name="action_drawer_open">Navigation öffnen</string>
<string name="action_drawer_close">Navigation schließen</string> <string name="action_drawer_close">Navigation schließen</string>
<string name="action_recent">Zuletzt geändert</string>
<string name="action_uncategorized">Ohne Kategorie</string> <string name="action_uncategorized">Ohne Kategorie</string>
<string name="menu_delete">Löschen</string> <string name="menu_delete">Löschen</string>
<string name="menu_change_category">Kategorie</string> <string name="menu_change_category">Kategorie</string>
<string name="menu_favorite">Favorit</string> <string name="menu_favorite">Favorit</string>
<string name="menu_preview">Vorschau</string> <string name="menu_preview">Vorschau</string>
<string name="menu_share">Teilen</string> <string name="menu_share">Teilen</string>
<string name="menu_about">Über</string>
<string name="change_category_title">Kategorie auswählen</string> <string name="change_category_title">Kategorie auswählen</string>
<string name="listview_updated_today">Heute</string> <string name="listview_updated_today">Heute</string>
<string name="listview_updated_yesterday">Gestern</string> <string name="listview_updated_yesterday">Gestern</string>
<string name="listview_updated_this_week">Diese Woche</string> <string name="listview_updated_this_week">Diese Woche</string>
<string name="listview_updated_last_week">Letzte Woche</string>
<string name="listview_updated_this_month">Diesen Monat</string> <string name="listview_updated_this_month">Diesen Monat</string>
<string name="listview_updated_earlier">Früher</string> <string name="listview_updated_last_month">Letzten Monat</string>
<!-- Settings --> <!-- Settings -->
<string name="settings_server_settings">Konto</string>
<string name="settings_url">Serveradresse</string>
<string name="settings_url_check_description">Zeigt an, ob die angegebene Adresse erreichbar ist.</string>
<string name="settings_url_warn_http">WARNUNG: "http" ist unsicher. Bitte benutzen Sie "https".</string>
<string name="settings_username">Benutzername</string>
<string name="settings_password">Passwort</string>
<string name="settings_password_unchanged">Passwort (nicht geändert)</string>
<string name="settings_password_check_description">Zeigt an, ob die angegebenen Zugangsdaten korrekt sind.</string>
<string name="settings_submit">Verbinden</string>
<string name="settings_submitting">Verbindet&#8230;</string>
<string name="settings_note_mode">Anzeigemodus für Notizen</string> <string name="settings_note_mode">Anzeigemodus für Notizen</string>
<string name="settings_theme_title">Dunkles Design</string> <string name="settings_theme_title">Dunkles Design</string>
<string name="settings_font_title">Nichtproportionale Schriftart</string> <string name="settings_font_title">Nichtproportionale Schriftart</string>
<string name="settings_font_size">Schriftgröße</string> <string name="settings_font_size">Schriftgröße</string>
<string name="settings_wifi_only">Nur über WLAN synchronisieren</string> <string name="settings_wifi_only">Nur über WLAN synchronisieren</string>
<string name="settings_cert_category">Zertifikate verwalten</string>
<string name="settings_cert_trust_system">System-Zertifikaten vertrauen</string>
<string name="settings_cert_trust_system_on">System- und installierten CAs wird vertraut (empfohlen)</string>
<string name="settings_cert_trust_system_off">System- und installierten CAs wird nicht vertraut</string>
<string name="settings_cert_reset">Zertifikat-Vertrauen zurücksetzen</string>
<string name="settings_cert_reset_summary">Setzt angenommene/abgelehnte Zertifikate zurück</string>
<string name="settings_cert_reset_toast">Alle Informationen über angenommene/abgelehnte Zertifikate wurden zurückgesetzt</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notizen - Verbindungssicherheit</string>
<string name="trust_certificate_unknown_certificate_found">Der Server nutzt ein unbekanntes Zertifikat. Soll diesem Zertifikat vertraut werden?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Verbinde</string>
<string name="network_connected">Verbunden</string>
<string name="network_disconnected">Kein Netzwerk verfügbar</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Synchronisation fehlgeschlagen: %1$s</string> <string name="error_sync">Synchronisation fehlgeschlagen: %1$s</string>
<string name="error_invalid_login">Anmeldung fehlgeschlagen: %1$s</string>
<string name="error_json">ist die Notes-App auf dem Server aktiviert?</string> <string name="error_json">ist die Notes-App auf dem Server aktiviert?</string>
<string name="error_io">Server-Verbindung nicht möglich</string>
<string name="error_no_network">keine Netzwerk-Verbindung</string> <string name="error_no_network">keine Netzwerk-Verbindung</string>
<string name="error_server">URL/Server fehlerhaft</string>
<string name="error_url_malformed">Falsche Serveradresse</string>
<string name="error_username_password_invalid">Benutzername oder Passwort falsch</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Einstellungen</string>
<!-- About --> <!-- About -->
<string name="about_version_title">Version</string> <string name="about_version_title">Version</string>
@ -127,7 +92,6 @@
<string name="shortcut_create_long">Neue Notiz erstellen</string> <string name="shortcut_create_long">Neue Notiz erstellen</string>
<string name="pref_value_theme_light">Hell</string> <string name="pref_value_theme_light">Hell</string>
<string name="pref_value_theme_dark">Dunkel</string>
<string name="pref_value_font_normal">Normal</string> <string name="pref_value_font_normal">Normal</string>
<string name="pref_value_wifi_and_mobile">Über WLAN und mobile Daten synchronisieren</string> <string name="pref_value_wifi_and_mobile">Über WLAN und mobile Daten synchronisieren</string>
<string name="simple_error">Fehler</string> <string name="simple_error">Fehler</string>
@ -137,6 +101,14 @@
<string name="copied_to_clipboard">In die Zwischenablage kopiert</string> <string name="copied_to_clipboard">In die Zwischenablage kopiert</string>
<string name="pin_to_homescreen">An Startbildschirm anheften</string> <string name="pin_to_homescreen">An Startbildschirm anheften</string>
<string name="note_has_been_deleted">Diese Notiz wurde gelöscht</string> <string name="note_has_been_deleted">Diese Notiz wurde gelöscht</string>
<string name="add_account">Konto hinzufügen</string>
<string name="category_music">Musik</string>
<string name="category_movies">Filme</string>
<string name="category_movie">Film</string>
<string name="category_work">Arbeit</string>
<string name="account_already_imported">Konto wurde bereits importiert</string>
<string name="no_notes_yet">Noch keine Notizen vorhanden</string>
<string name="no_notes_yet_description">Drücke den \"+\"-Knopf um eine neue Notiz zu erstellen</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">

View file

@ -2,77 +2,56 @@
<resources> <resources>
<string name="app_name">Σημειώσεις</string> <string name="app_name">Σημειώσεις</string>
<string name="no_notes">Δεν υπάρχουν ακόμα σημειώσεις</string> <string name="app_name_long">Nextcloud Σημειώσεις</string>
<string name="label_all_notes">Όλες οι σημειώσεις</string> <string name="label_all_notes">Όλες οι σημειώσεις</string>
<string name="label_favorites">Αγαπημένα</string> <string name="label_favorites">Αγαπημένα</string>
<string name="action_create">Νέα σημείωση</string> <string name="action_create">Νέα σημείωση</string>
<string name="action_settings">Ρυθμίσεις</string> <string name="action_settings">Ρυθμίσεις</string>
<string name="action_trashbin">Διεγραμμένες σημειώσεις</string> <string name="action_trashbin">Διεγραμμένες σημειώσεις</string>
<string name="action_search">Ψάχνει</string> <string name="action_search">Ψάχνει</string>
<string name="action_create_save">Αποθήκευση</string>
<string name="simple_cancel">Άκυρο</string> <string name="simple_cancel">Άκυρο</string>
<string name="simple_edit">Επεξεργασία</string> <string name="simple_edit">Επεξεργασία</string>
<string name="action_edit_save">Αποθήκευση</string> <string name="action_edit_save">Αποθήκευση</string>
<string name="action_edit_saving">Γίνεται αποθήκευση &#8230;</string>
<string name="action_edit_saved">Αποθηκεύτηκε</string>
<string name="simple_about">Περί</string> <string name="simple_about">Περί</string>
<string name="action_select_note">Επιλογή σημείωσης</string> <string name="simple_bold">Έντονα</string>
<string name="simple_link">Σύνδεσμος</string>
<string name="simple_italic">Πλάγια</string>
<string name="action_note_deleted">Η σημείωση διαγράφηκε.</string> <string name="action_note_deleted">Η σημείωση διαγράφηκε.</string>
<string name="action_note_restored">Έγινε επαναφορά της σημείωσης.</string> <string name="action_note_restored">Έγινε επαναφορά της σημείωσης.</string>
<string name="action_undo">Αναίρεση</string> <string name="action_undo">Αναίρεση</string>
<string name="action_drawer_open">Άνοιγμα πλοήγησης</string> <string name="action_drawer_open">Άνοιγμα πλοήγησης</string>
<string name="action_drawer_close">Κλείσιμο πλοήγησης</string> <string name="action_drawer_close">Κλείσιμο πλοήγησης</string>
<string name="action_recent">Πρόσφατα</string>
<string name="action_uncategorized">Μή-κατηγοριοποιημένα</string> <string name="action_uncategorized">Μή-κατηγοριοποιημένα</string>
<string name="menu_delete">Διαγραφή</string> <string name="menu_delete">Διαγραφή</string>
<string name="menu_change_category">Κατηγορία</string> <string name="menu_change_category">Κατηγορία</string>
<string name="menu_favorite">Αγαπημένο</string> <string name="menu_favorite">Αγαπημένο</string>
<string name="menu_preview">Προεπισκόπηση</string> <string name="menu_preview">Προεπισκόπηση</string>
<string name="menu_share">Διαμοιρασμός</string> <string name="menu_share">Διαμοιρασμός</string>
<string name="menu_about">Περί</string>
<string name="change_category_title">Επιλογή κατηγορίας</string> <string name="change_category_title">Επιλογή κατηγορίας</string>
<string name="listview_updated_today">Σήμερα</string> <string name="listview_updated_today">Σήμερα</string>
<string name="listview_updated_yesterday">Χθες</string> <string name="listview_updated_yesterday">Χθες</string>
<string name="listview_updated_this_week">Αυτή την εβδομάδα</string> <string name="listview_updated_this_week">Αυτή την εβδομάδα</string>
<string name="listview_updated_last_week">Προηγούμενη εβδομάδα</string>
<string name="listview_updated_this_month">Αυτό το μήνα</string> <string name="listview_updated_this_month">Αυτό το μήνα</string>
<string name="listview_updated_earlier">Νωρίτερα</string> <string name="listview_updated_last_month">Προηγούμενος μήνας</string>
<!-- Settings --> <!-- Settings -->
<string name="settings_server_settings">Λογαριαμός</string> <string name="settings_note_mode">Κατάσταση οθόνης για σημειώσεις</string>
<string name="settings_url">Διεύθυνση διακομιστή</string> <string name="settings_theme_title">Σκούρο θέμα</string>
<string name="settings_url_warn_http">ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Το \"http\" δεν είναι ασφαλές. Παρακαλούμε χρησιμοποιήστε το \"https\".</string> <string name="settings_font_title">Γραμματοσειρά monospace</string>
<string name="settings_username">Όνομα χρήστη</string> <string name="settings_font_size">Μέγεθος γραμματοσειράς</string>
<string name="settings_password">Συνθηματικό</string>
<string name="settings_password_unchanged">Συνθηματικό (δεν άλλαξε)</string>
<string name="settings_submit">Σύνδεση</string>
<string name="settings_submitting">Συνδέεται &#8230;</string>
<string name="settings_wifi_only">Συγχρονισμός μόνο σε Wi-Fi</string> <string name="settings_wifi_only">Συγχρονισμός μόνο σε Wi-Fi</string>
<string name="settings_cert_category">Διαχείριση πιστοποιητικών</string>
<string name="settings_cert_trust_system">Εμπιστοσύνη πιστοποιητικών συστήματος.</string>
<string name="settings_cert_reset">Επαναφορά (μη) έμπιστων πιστοποιητικών</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Σημειώσεις - Ασφάλεια σύνδεσης</string>
<string name="trust_certificate_unknown_certificate_found">Οι Σημειώσεις έχουν συναντήσει ένα άγνωστο πιστοποιητικό. Θέλετε να το εμπιστεύεστε;</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Συνδέεται</string>
<string name="network_connected">Συνδέθηκε</string>
<string name="network_disconnected">Δεν υπάρχει διαθέσιμο δίκτυο</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Αποτυχία συγχρονισμού: %1$s</string> <string name="error_sync">Αποτυχία συγχρονισμού: %1$s</string>
<string name="error_invalid_login">Μη έγκυρη είσοδος: %1$s</string>
<string name="error_json">Είναι η εφαρμογή Σημειώσεις ενεργοποιημένη στον εξυπηρετητή Nextcloud;</string> <string name="error_json">Είναι η εφαρμογή Σημειώσεις ενεργοποιημένη στον εξυπηρετητή Nextcloud;</string>
<string name="error_io">η σύνδεση του διακομιστή είναι προβληματική</string>
<string name="error_no_network">δεν υπάρχει σύνδεση δικτύου</string> <string name="error_no_network">δεν υπάρχει σύνδεση δικτύου</string>
<string name="error_server">URL/Διακομιστής έχει σφάλματα</string>
<string name="error_url_malformed">Εσφαλμένη διεύθυνση διακομιστή</string>
<string name="error_username_password_invalid">Εσφαλμένο όνομα χρήστη ή συνθηματικό</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Ρυθμίσεις</string>
<!-- About --> <!-- About -->
<string name="about_version_title">Έκδοση</string> <string name="about_version_title">Έκδοση</string>
@ -92,6 +71,7 @@
<string name="about_app_license">Αυτή η εφαρμογή υπόκεινται στην άδεια χρήσης GNU GENERAL PUBLIC LICENSE v3+.</string> <string name="about_app_license">Αυτή η εφαρμογή υπόκεινται στην άδεια χρήσης GNU GENERAL PUBLIC LICENSE v3+.</string>
<string name="about_app_license_button">Προβολή άδειας χρήσης</string> <string name="about_app_license_button">Προβολή άδειας χρήσης</string>
<string name="about_icons_disclaimer_title">Εικονίδια</string> <string name="about_icons_disclaimer_title">Εικονίδια</string>
<string name="about_icons_disclaimer">&lt;p>Τα αυθεντικά εικονίδια δημιουργήθηκαν από %1$s&lt;/p>&lt; p> Όλα τα υπόλοιπα αυτής της εφαρμογής είναι &lt; href=\"https://materialdesignicons.com/\">Material Design Icons&lt;/a> made by Google Inc. and licensed under the Apache 2.0 License.&lt;/p></string>
<string name="about_credits_tab_title">Μνεία</string> <string name="about_credits_tab_title">Μνεία</string>
<string name="about_contribution_tab_title">Συνεισφορά</string> <string name="about_contribution_tab_title">Συνεισφορά</string>
<string name="about_license_tab_title">Άδεια χρήσης</string> <string name="about_license_tab_title">Άδεια χρήσης</string>
@ -103,6 +83,7 @@
<string name="widget_single_note_placeholder_tv">Η σημείωση δεν βρέθηκε</string> <string name="widget_single_note_placeholder_tv">Η σημείωση δεν βρέθηκε</string>
<string name="widget_create_note">Δημιουργία Σημείωσης</string> <string name="widget_create_note">Δημιουργία Σημείωσης</string>
<string name="widget_not_logged_in">Παρακαλούμε συνδεθείτε στις Σημειώσεις πρωτού να χρησιμοποιήσετε αυτό το γραφικό στοιχείο.</string> <string name="widget_not_logged_in">Παρακαλούμε συνδεθείτε στις Σημειώσεις πρωτού να χρησιμοποιήσετε αυτό το γραφικό στοιχείο.</string>
<string name="widget_entry_fav_contentDescription">Το εικονίδιο Αστέρι χρησιμέυει για την σήμανση ως αγαπημένο</string>
<string name="widget_app_launcher_contentDescription">Εκκινεί την εφαρμογή</string> <string name="widget_app_launcher_contentDescription">Εκκινεί την εφαρμογή</string>
<string name="activity_select_single_note">Επιλογή σημείωσης</string> <string name="activity_select_single_note">Επιλογή σημείωσης</string>
@ -111,8 +92,24 @@
<string name="shortcut_create_long">Δημιουργία νέας σημείωσης</string> <string name="shortcut_create_long">Δημιουργία νέας σημείωσης</string>
<string name="pref_value_theme_light">Φωτεινό</string> <string name="pref_value_theme_light">Φωτεινό</string>
<string name="pref_value_theme_dark">Σκοτεινό</string> <string name="pref_value_font_normal">Κανονικό</string>
<string name="pref_value_wifi_and_mobile">Συγχρονισμός μόνο σε Wi-Fi και δεδομένα κινητού</string> <string name="pref_value_wifi_and_mobile">Συγχρονισμός μόνο σε Wi-Fi και δεδομένα κινητού</string>
<string name="simple_error">Σφάλμα</string>
<string name="simple_close">Κλείσιμο</string>
<string name="simple_copy">Αντιγραφή</string>
<string name="simple_exception">Εξαίρεση</string>
<string name="copied_to_clipboard">Αντιγράφηκε στο πρόχειρο</string>
<string name="pin_to_homescreen">Καρφίτσωμα στην αρχική αθόνη</string>
<string name="note_has_been_deleted">Αυτή η σημείωση έχει διαγραφεί</string>
<string name="add_account">Προσθήκη λογαριασμού</string>
<string name="category_music">Μουσική</string>
<string name="category_movies">Ταινίες</string>
<string name="category_movie">Ταινία</string>
<string name="category_work">Εργασία</string>
<string name="account_already_imported">Ο λογαριασμός έχει εισαχθεί ήδη</string>
<string name="no_notes_yet">Δεν υπάρχουν ακόμα σημειώσεις</string>
<string name="no_notes_yet_description">Πιέστε το κουμπί + για νέα σημείωση</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Άνοιγμα σε λειτουργία τροποποίησης</item> <item>Άνοιγμα σε λειτουργία τροποποίησης</item>
@ -120,6 +117,13 @@
<item>Να θυμάσαι την τελευταία μου επιλογή</item> <item>Να θυμάσαι την τελευταία μου επιλογή</item>
</string-array> </string-array>
<!-- Array: font size -->
<string-array name="fontSize_entries">
<item>Μικρό</item>
<item>Μεσαίο</item>
<item>Μεγάλο</item>
</string-array>
<!-- Plurals --> <!-- Plurals -->
<plurals name="ab_selected"> <plurals name="ab_selected">
<item quantity="one">%d επιλέχτηκε</item> <item quantity="one">%d επιλέχτηκε</item>

View file

@ -2,89 +2,45 @@
<resources> <resources>
<string name="app_name">Notes</string> <string name="app_name">Notes</string>
<string name="no_notes">No notes yet</string>
<string name="action_create">New note</string> <string name="action_create">New note</string>
<string name="action_settings">Settings</string> <string name="action_settings">Settings</string>
<string name="action_search">Search</string> <string name="action_search">Search</string>
<string name="action_create_save">Save</string>
<string name="simple_cancel">Cancel</string> <string name="simple_cancel">Cancel</string>
<string name="simple_edit">Edit</string> <string name="simple_edit">Edit</string>
<string name="action_edit_save">Save</string> <string name="action_edit_save">Save</string>
<string name="action_edit_saving">Saving &#8230;</string>
<string name="action_edit_saved">Saved</string>
<string name="action_edit_cancel">Cancel</string>
<string name="simple_about">About</string> <string name="simple_about">About</string>
<string name="action_select_note">Select note</string>
<string name="action_note_deleted">Note deleted</string> <string name="action_note_deleted">Note deleted</string>
<string name="action_note_restored">Note restored</string> <string name="action_note_restored">Note restored</string>
<string name="action_undo">Undo</string> <string name="action_undo">Undo</string>
<string name="action_drawer_open">open navigation</string> <string name="action_drawer_open">open navigation</string>
<string name="action_drawer_close">close navigation</string> <string name="action_drawer_close">close navigation</string>
<string name="action_recent">Recent</string>
<string name="action_starred">Starred</string>
<string name="action_uncategorized">Uncategorised</string> <string name="action_uncategorized">Uncategorised</string>
<string name="menu_delete">Delete</string> <string name="menu_delete">Delete</string>
<string name="menu_copy">Copy</string>
<string name="menu_edit">Edit</string>
<string name="menu_cancel">Cancel</string>
<string name="menu_change_category">Category</string> <string name="menu_change_category">Category</string>
<string name="menu_favorite">Favourite</string> <string name="menu_favorite">Favourite</string>
<string name="menu_preview">Preview</string> <string name="menu_preview">Preview</string>
<string name="menu_share">Share</string> <string name="menu_share">Share</string>
<string name="menu_about">About</string>
<string name="change_category_title">Choose category</string> <string name="change_category_title">Choose category</string>
<string name="copy">Copy</string>
<string name="listview_updated_today">Today</string> <string name="listview_updated_today">Today</string>
<string name="listview_updated_yesterday">Yesterday</string> <string name="listview_updated_yesterday">Yesterday</string>
<string name="listview_updated_this_week">This week</string> <string name="listview_updated_this_week">This week</string>
<string name="listview_updated_this_month">This month</string> <string name="listview_updated_this_month">This month</string>
<string name="listview_updated_earlier">Earlier</string>
<!-- Settings --> <!-- Settings -->
<string name="settings_server_settings">Account</string>
<string name="settings_url">Server address</string>
<string name="settings_url_check_description">Shows whether the address can be pinged.</string>
<string name="settings_url_warn_http">WARNING: \"http\" is unsafe. Please use \"https\".</string>
<string name="settings_username">Username</string>
<string name="settings_password">Password</string>
<string name="settings_password_unchanged">Password (not changed)</string>
<string name="settings_password_check_description">Displays whether the credentials are correct.</string>
<string name="settings_submit">Connect</string>
<string name="settings_submitting">Connecting &#8230;</string>
<string name="settings_note_mode">Display mode for Notes</string> <string name="settings_note_mode">Display mode for Notes</string>
<string name="settings_notification_title">\"Create note\" as notification</string>
<string name="settings_notification">Enable to show a persistent notification for quickly creating new notes.</string>
<string name="settings_cert_category">Manage certificates</string>
<string name="settings_cert_trust_system">Trust system certificates</string>
<string name="settings_cert_trust_system_on">System and user-added CAs will be trusted (recommended)</string>
<string name="settings_cert_trust_system_off">System and user-added CAs won\'t be trusted</string>
<string name="settings_cert_reset">Reset (un)trusted certificates</string>
<string name="settings_cert_reset_summary">Resets trust of all custom certificates</string>
<string name="settings_cert_reset_toast">All custom certificates have been cleared</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notes - Connection security</string>
<string name="trust_certificate_unknown_certificate_found">Notes has encountered an unknown certificate. Do you want to trust it?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Connecting</string>
<string name="network_connected">Connected</string>
<string name="network_disconnected">No network available</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Synchronisation failed: %1$s</string> <string name="error_sync">Synchronisation failed: %1$s</string>
<string name="error_invalid_login">Invalid login: %1$s</string>
<string name="error_json">is the Notes app activated on the server?</string> <string name="error_json">is the Notes app activated on the server?</string>
<string name="error_io">server connection is broken</string>
<string name="error_no_network">no network connection</string> <string name="error_no_network">no network connection</string>
<string name="error_server">URL/Server has errors</string>
<string name="error_url_malformed">Wrong server address</string>
<string name="error_username_password_invalid">Wrong username or password</string>
<!-- Snackbar Actions --> <!-- Snackbar Actions -->
<string name="snackbar_settings">Settings</string>
<!-- About --> <!-- About -->
<string name="about_version_title">Version</string> <string name="about_version_title">Version</string>

View file

@ -2,75 +2,39 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="action_create">Nueva nota</string> <string name="action_create">Nueva nota</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_create_save">Guardar</string>
<string name="simple_cancel">Cancelar</string> <string name="simple_cancel">Cancelar</string>
<string name="simple_edit">Editar</string> <string name="simple_edit">Editar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="action_edit_cancel">Cancelar</string>
<string name="simple_about">Acerca de</string> <string name="simple_about">Acerca de</string>
<string name="action_select_note">Seleccionar nota</string>
<string name="action_note_deleted">La nota ha sido borrada</string> <string name="action_note_deleted">La nota ha sido borrada</string>
<string name="action_note_restored">La nota ha sido restaurada</string> <string name="action_note_restored">La nota ha sido restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_copy">Copiar</string>
<string name="menu_edit">Editar</string>
<string name="menu_cancel">Cancelar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="change_category_title">Elige categoría</string> <string name="change_category_title">Elige categoría</string>
<string name="change_category_message">Favor de ingresar nombre de categoría</string>
<string name="copy">Copiar</string>
<string name="listview_updated_today">Hoy</string> <string name="listview_updated_today">Hoy</string>
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<!-- Settings --> <!-- Settings -->
<string name="settings_server_settings">Configuraciones de la cuenta</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si se puede hacer ping a la dirección</string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Favor de usar \"https\".</string>
<string name="settings_username">Nombre de usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_category">Certificados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido.
Desea confiar en el mismo?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Nombre de usuario o contraseña incorrecto</string>
<!-- Snackbar Actions --> <!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>
@ -95,7 +59,6 @@ Desea confiar en el mismo?</string>
<string name="about_contribution_tab_title">Contribución</string> <string name="about_contribution_tab_title">Contribución</string>
<string name="about_license_tab_title">Licencia</string> <string name="about_license_tab_title">Licencia</string>
<string name="widget_all_notes_title">Todas la notas</string>
<string name="widget_single_note_title">Única nota</string> <string name="widget_single_note_title">Única nota</string>
<string name="widget_create_note">Crear Nota</string> <string name="widget_create_note">Crear Nota</string>

View file

@ -2,33 +2,28 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="label_all_notes">Todas las notas</string> <string name="label_all_notes">Todas las notas</string>
<string name="label_favorites">Favoritos</string> <string name="label_favorites">Favoritos</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_trashbin">Notas borradas</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="simple_cancel">Cancelar</string> <string name="simple_cancel">Cancelar</string>
<string name="simple_edit">Editar</string> <string name="simple_edit">Editar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="simple_about">Acerca de</string> <string name="simple_about">Acerca de</string>
<string name="action_select_note">Seleccionar nota</string> <string name="simple_link">Liga</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="change_category_title">Elige una categoría</string> <string name="change_category_title">Elige una categoría</string>
@ -36,45 +31,14 @@
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>
@ -115,7 +79,14 @@
<string name="shortcut_create_long">Crear una nota nueva</string> <string name="shortcut_create_long">Crear una nota nueva</string>
<string name="pref_value_theme_light">Claro</string> <string name="pref_value_theme_light">Claro</string>
<string name="pref_value_theme_dark">Oscuro</string> <string name="pref_value_font_normal">Normal</string>
<string name="simple_error">Error</string>
<string name="simple_close">Cerrar</string>
<string name="simple_copy">Copiar</string>
<string name="copied_to_clipboard">Copiado al portapapeles</string>
<string name="add_account">Agregar cuenta</string>
<string name="category_work">Trabajo</string>
<string name="no_notes_yet">Aún no hay notas</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Abrir en modo edición</item> <item>Abrir en modo edición</item>

View file

@ -2,33 +2,28 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="label_all_notes">Todas las notas</string> <string name="label_all_notes">Todas las notas</string>
<string name="label_favorites">Favoritos</string> <string name="label_favorites">Favoritos</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_trashbin">Notas borradas</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="simple_cancel">Cancelar</string> <string name="simple_cancel">Cancelar</string>
<string name="simple_edit">Editar</string> <string name="simple_edit">Editar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="simple_about">Acerca de</string> <string name="simple_about">Acerca de</string>
<string name="action_select_note">Seleccionar nota</string> <string name="simple_link">Liga</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="change_category_title">Elige una categoría</string> <string name="change_category_title">Elige una categoría</string>
@ -36,45 +31,14 @@
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>
@ -115,7 +79,14 @@
<string name="shortcut_create_long">Crear una nota nueva</string> <string name="shortcut_create_long">Crear una nota nueva</string>
<string name="pref_value_theme_light">Claro</string> <string name="pref_value_theme_light">Claro</string>
<string name="pref_value_theme_dark">Oscuro</string> <string name="pref_value_font_normal">Normal</string>
<string name="simple_error">Error</string>
<string name="simple_close">Cerrar</string>
<string name="simple_copy">Copiar</string>
<string name="copied_to_clipboard">Copiado al portapapeles</string>
<string name="add_account">Agregar cuenta</string>
<string name="category_work">Trabajo</string>
<string name="no_notes_yet">Aún no hay notas</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Abrir en modo edición</item> <item>Abrir en modo edición</item>

View file

@ -2,33 +2,28 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="label_all_notes">Todas las notas</string> <string name="label_all_notes">Todas las notas</string>
<string name="label_favorites">Favoritos</string> <string name="label_favorites">Favoritos</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_trashbin">Notas borradas</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="simple_cancel">Cancelar</string> <string name="simple_cancel">Cancelar</string>
<string name="simple_edit">Editar</string> <string name="simple_edit">Editar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="simple_about">Acerca de</string> <string name="simple_about">Acerca de</string>
<string name="action_select_note">Seleccionar nota</string> <string name="simple_link">Liga</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="change_category_title">Elige una categoría</string> <string name="change_category_title">Elige una categoría</string>
@ -36,45 +31,14 @@
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>
@ -115,7 +79,14 @@
<string name="shortcut_create_long">Crear una nota nueva</string> <string name="shortcut_create_long">Crear una nota nueva</string>
<string name="pref_value_theme_light">Claro</string> <string name="pref_value_theme_light">Claro</string>
<string name="pref_value_theme_dark">Oscuro</string> <string name="pref_value_font_normal">Normal</string>
<string name="simple_error">Error</string>
<string name="simple_close">Cerrar</string>
<string name="simple_copy">Copiar</string>
<string name="copied_to_clipboard">Copiado al portapapeles</string>
<string name="add_account">Agregar cuenta</string>
<string name="category_work">Trabajo</string>
<string name="no_notes_yet">Aún no hay notas</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Abrir en modo edición</item> <item>Abrir en modo edición</item>

View file

@ -2,33 +2,28 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="label_all_notes">Todas las notas</string> <string name="label_all_notes">Todas las notas</string>
<string name="label_favorites">Favoritos</string> <string name="label_favorites">Favoritos</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_trashbin">Notas borradas</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="simple_cancel">Cancelar</string> <string name="simple_cancel">Cancelar</string>
<string name="simple_edit">Editar</string> <string name="simple_edit">Editar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="simple_about">Acerca de</string> <string name="simple_about">Acerca de</string>
<string name="action_select_note">Seleccionar nota</string> <string name="simple_link">Liga</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="change_category_title">Elige una categoría</string> <string name="change_category_title">Elige una categoría</string>
@ -36,45 +31,14 @@
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>
@ -115,7 +79,14 @@
<string name="shortcut_create_long">Crear una nota nueva</string> <string name="shortcut_create_long">Crear una nota nueva</string>
<string name="pref_value_theme_light">Claro</string> <string name="pref_value_theme_light">Claro</string>
<string name="pref_value_theme_dark">Oscuro</string> <string name="pref_value_font_normal">Normal</string>
<string name="simple_error">Error</string>
<string name="simple_close">Cerrar</string>
<string name="simple_copy">Copiar</string>
<string name="copied_to_clipboard">Copiado al portapapeles</string>
<string name="add_account">Agregar cuenta</string>
<string name="category_work">Trabajo</string>
<string name="no_notes_yet">Aún no hay notas</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Abrir en modo edición</item> <item>Abrir en modo edición</item>

View file

@ -2,33 +2,28 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="label_all_notes">Todas las notas</string> <string name="label_all_notes">Todas las notas</string>
<string name="label_favorites">Favoritos</string> <string name="label_favorites">Favoritos</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_trashbin">Notas borradas</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="simple_cancel">Cancelar</string> <string name="simple_cancel">Cancelar</string>
<string name="simple_edit">Editar</string> <string name="simple_edit">Editar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="simple_about">Acerca de</string> <string name="simple_about">Acerca de</string>
<string name="action_select_note">Seleccionar nota</string> <string name="simple_link">Liga</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="change_category_title">Elige una categoría</string> <string name="change_category_title">Elige una categoría</string>
@ -36,45 +31,14 @@
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>
@ -115,7 +79,14 @@
<string name="shortcut_create_long">Crear una nota nueva</string> <string name="shortcut_create_long">Crear una nota nueva</string>
<string name="pref_value_theme_light">Claro</string> <string name="pref_value_theme_light">Claro</string>
<string name="pref_value_theme_dark">Oscuro</string> <string name="pref_value_font_normal">Normal</string>
<string name="simple_error">Error</string>
<string name="simple_close">Cerrar</string>
<string name="simple_copy">Copiar</string>
<string name="copied_to_clipboard">Copiado al portapapeles</string>
<string name="add_account">Agregar cuenta</string>
<string name="category_work">Trabajo</string>
<string name="no_notes_yet">Aún no hay notas</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Abrir en modo edición</item> <item>Abrir en modo edición</item>

View file

@ -2,33 +2,28 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="label_all_notes">Todas las notas</string> <string name="label_all_notes">Todas las notas</string>
<string name="label_favorites">Favoritos</string> <string name="label_favorites">Favoritos</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_trashbin">Notas borradas</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="simple_cancel">Cancelar</string> <string name="simple_cancel">Cancelar</string>
<string name="simple_edit">Editar</string> <string name="simple_edit">Editar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="simple_about">Acerca de</string> <string name="simple_about">Acerca de</string>
<string name="action_select_note">Seleccionar nota</string> <string name="simple_link">Liga</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="change_category_title">Elige una categoría</string> <string name="change_category_title">Elige una categoría</string>
@ -36,45 +31,14 @@
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>
@ -115,7 +79,14 @@
<string name="shortcut_create_long">Crear una nota nueva</string> <string name="shortcut_create_long">Crear una nota nueva</string>
<string name="pref_value_theme_light">Claro</string> <string name="pref_value_theme_light">Claro</string>
<string name="pref_value_theme_dark">Oscuro</string> <string name="pref_value_font_normal">Normal</string>
<string name="simple_error">Error</string>
<string name="simple_close">Cerrar</string>
<string name="simple_copy">Copiar</string>
<string name="copied_to_clipboard">Copiado al portapapeles</string>
<string name="add_account">Agregar cuenta</string>
<string name="category_work">Trabajo</string>
<string name="no_notes_yet">Aún no hay notas</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Abrir en modo edición</item> <item>Abrir en modo edición</item>

View file

@ -2,72 +2,37 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="action_select_note">Seleccionar nota</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="listview_updated_today">Hoy</string> <string name="listview_updated_today">Hoy</string>
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions --> <!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>

View file

@ -2,33 +2,30 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="label_all_notes">Todas las notas</string> <string name="label_all_notes">Todas las notas</string>
<string name="label_favorites">Favoritos</string> <string name="label_favorites">Favoritos</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_trashbin">Notas borradas</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="simple_cancel">Cancelar</string> <string name="simple_cancel">Cancelar</string>
<string name="simple_edit">Editar</string> <string name="simple_edit">Editar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="simple_about">Acerca de</string> <string name="simple_about">Acerca de</string>
<string name="action_select_note">Seleccionar nota</string> <string name="simple_bold">Negritas</string>
<string name="simple_link">Liga</string>
<string name="simple_italic">Cursiva</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="change_category_title">Elige una categoría</string> <string name="change_category_title">Elige una categoría</string>
@ -36,45 +33,14 @@
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>
@ -115,7 +81,14 @@
<string name="shortcut_create_long">Crear una nota nueva</string> <string name="shortcut_create_long">Crear una nota nueva</string>
<string name="pref_value_theme_light">Claro</string> <string name="pref_value_theme_light">Claro</string>
<string name="pref_value_theme_dark">Oscuro</string> <string name="pref_value_font_normal">Normal</string>
<string name="simple_error">Error</string>
<string name="simple_close">Cerrar</string>
<string name="simple_copy">Copiar</string>
<string name="copied_to_clipboard">Copiado al portapapeles</string>
<string name="add_account">Agregar cuenta</string>
<string name="category_work">Trabajo</string>
<string name="no_notes_yet">Aún no hay notas</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Abrir en modo edición</item> <item>Abrir en modo edición</item>

View file

@ -2,72 +2,37 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="action_select_note">Seleccionar nota</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="listview_updated_today">Hoy</string> <string name="listview_updated_today">Hoy</string>
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions --> <!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>

View file

@ -2,72 +2,37 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="action_select_note">Seleccionar nota</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="listview_updated_today">Hoy</string> <string name="listview_updated_today">Hoy</string>
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions --> <!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>

View file

@ -2,72 +2,37 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="action_select_note">Seleccionar nota</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="listview_updated_today">Hoy</string> <string name="listview_updated_today">Hoy</string>
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions --> <!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>

View file

@ -2,72 +2,37 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="action_select_note">Seleccionar nota</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="listview_updated_today">Hoy</string> <string name="listview_updated_today">Hoy</string>
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions --> <!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>

View file

@ -2,72 +2,37 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="action_select_note">Seleccionar nota</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="listview_updated_today">Hoy</string> <string name="listview_updated_today">Hoy</string>
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions --> <!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>

View file

@ -2,33 +2,28 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="label_all_notes">Todas las notas</string> <string name="label_all_notes">Todas las notas</string>
<string name="label_favorites">Favoritos</string> <string name="label_favorites">Favoritos</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_trashbin">Notas borradas</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="simple_cancel">Cancelar</string> <string name="simple_cancel">Cancelar</string>
<string name="simple_edit">Editar</string> <string name="simple_edit">Editar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="simple_about">Acerca de</string> <string name="simple_about">Acerca de</string>
<string name="action_select_note">Seleccionar nota</string> <string name="simple_link">Liga</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="change_category_title">Elige una categoría</string> <string name="change_category_title">Elige una categoría</string>
@ -36,45 +31,14 @@
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>
@ -115,7 +79,14 @@
<string name="shortcut_create_long">Crear una nota nueva</string> <string name="shortcut_create_long">Crear una nota nueva</string>
<string name="pref_value_theme_light">Claro</string> <string name="pref_value_theme_light">Claro</string>
<string name="pref_value_theme_dark">Oscuro</string> <string name="pref_value_font_normal">Normal</string>
<string name="simple_error">Error</string>
<string name="simple_close">Cerrar</string>
<string name="simple_copy">Copiar</string>
<string name="copied_to_clipboard">Copiado al portapapeles</string>
<string name="add_account">Agregar cuenta</string>
<string name="category_work">Trabajo</string>
<string name="no_notes_yet">Aún no hay notas</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Abrir en modo edición</item> <item>Abrir en modo edición</item>

View file

@ -2,72 +2,37 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string>
<string name="action_create">Nota nueva</string> <string name="action_create">Nota nueva</string>
<string name="action_settings">Configuraciones</string> <string name="action_settings">Configuraciones</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="action_select_note">Seleccionar nota</string>
<string name="action_note_deleted">Nota borrada</string> <string name="action_note_deleted">Nota borrada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Vista previa</string> <string name="menu_preview">Vista previa</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="listview_updated_today">Hoy</string> <string name="listview_updated_today">Hoy</string>
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Anterior</string>
<string name="settings_url">Dirección del servidor</string>
<string name="settings_url_check_description">Muestra si a la dirección se le puede hacer un ping. </string>
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" no es seguro. Por favor usa \"https\".</string>
<string name="settings_username">Usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Los CAs del sistema y del usuario serán de confianza (recomendado)</string>
<string name="settings_cert_trust_system_off">Los CAs del sistema y de usuarios no serán de confianza</string>
<string name="settings_cert_reset">Reiniciar los certificados (no) de confianza</string>
<string name="settings_cert_reset_summary">Reinicia la confizanza de todos los certificados personalizados</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido borrados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Deseas confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Falló la sincronización: %1$s</string> <string name="error_sync">Falló la sincronización: %1$s</string>
<string name="error_invalid_login">Inicio de sesión inválido: %1$s</string>
<string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string> <string name="error_json">¿Se encuentra activiada la aplicación de Notes en el servidor?</string>
<string name="error_io">se ha interrumpido al conexión al servidor</string>
<string name="error_no_network">no hay conexión a red</string> <string name="error_no_network">no hay conexión a red</string>
<string name="error_server">La URL / Servidor tiene errores</string>
<string name="error_url_malformed">La dirección del servidor es incorrecta</string>
<string name="error_username_password_invalid">Usuario o contraseña incorrecto</string>
<!-- Snackbar Actions --> <!-- Snackbar Actions -->
<string name="snackbar_settings">Configuraciones </string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>

View file

@ -2,91 +2,56 @@
<resources> <resources>
<string name="app_name">Notas</string> <string name="app_name">Notas</string>
<string name="no_notes">Aún no hay notas</string> <string name="app_name_long">Nextcloud Notas</string>
<string name="label_all_notes">Todas las notas</string> <string name="label_all_notes">Todas las notas</string>
<string name="label_favorites">Favoritos</string> <string name="label_favorites">Favoritos</string>
<string name="action_create">Nueva nota</string> <string name="action_create">Nueva nota</string>
<string name="action_settings">Ajustes</string> <string name="action_settings">Ajustes</string>
<string name="action_trashbin">Notas eliminadas</string> <string name="action_trashbin">Notas eliminadas</string>
<string name="action_search">Buscar</string> <string name="action_search">Buscar</string>
<string name="action_create_save">Guardar</string>
<string name="simple_cancel">Cancelar</string> <string name="simple_cancel">Cancelar</string>
<string name="simple_edit">Editar</string> <string name="simple_edit">Editar</string>
<string name="action_edit_save">Guardar</string> <string name="action_edit_save">Guardar</string>
<string name="action_edit_saving">Guardando &#8230;</string>
<string name="action_edit_saved">Guardado</string>
<string name="simple_about">Acerca de</string> <string name="simple_about">Acerca de</string>
<string name="simple_bold">Negrita</string> <string name="simple_bold">Negrita</string>
<string name="simple_link">Enlace</string> <string name="simple_link">Enlace</string>
<string name="simple_italic">Cursiva</string> <string name="simple_italic">Cursiva</string>
<string name="action_select_note">Seleccionar nota</string>
<string name="action_note_deleted">Nota eliminada</string> <string name="action_note_deleted">Nota eliminada</string>
<string name="action_note_restored">Nota restaurada</string> <string name="action_note_restored">Nota restaurada</string>
<string name="action_undo">Deshacer</string> <string name="action_undo">Deshacer</string>
<string name="action_drawer_open">abrir navegación</string> <string name="action_drawer_open">abrir navegación</string>
<string name="action_drawer_close">cerrar navegación</string> <string name="action_drawer_close">cerrar navegación</string>
<string name="action_recent">Reciente</string>
<string name="action_uncategorized">Sin categoría</string> <string name="action_uncategorized">Sin categoría</string>
<string name="menu_delete">Borrar</string> <string name="menu_delete">Borrar</string>
<string name="menu_change_category">Categoría</string> <string name="menu_change_category">Categoría</string>
<string name="menu_favorite">Favorito</string> <string name="menu_favorite">Favorito</string>
<string name="menu_preview">Previsualizar</string> <string name="menu_preview">Previsualizar</string>
<string name="menu_share">Compartir</string> <string name="menu_share">Compartir</string>
<string name="menu_about">Acerca de</string>
<string name="change_category_title">Escoge una categoría</string> <string name="change_category_title">Escoge una categoría</string>
<string name="listview_updated_today">Hoy</string> <string name="listview_updated_today">Hoy</string>
<string name="listview_updated_yesterday">Ayer</string> <string name="listview_updated_yesterday">Ayer</string>
<string name="listview_updated_this_week">Esta semana</string> <string name="listview_updated_this_week">Esta semana</string>
<string name="listview_updated_last_week">La semana pasada</string>
<string name="listview_updated_this_month">Este mes</string> <string name="listview_updated_this_month">Este mes</string>
<string name="listview_updated_earlier">Recientemente</string> <string name="listview_updated_last_month">El mes pasado</string>
<!-- Settings --> <!-- Settings -->
<string name="settings_server_settings">Cuenta</string>
<string name="settings_url">Dirección de servidor</string>
<string name="settings_url_check_description">Muestra si se puede hacer ping a la dirección.</string>
<string name="settings_url_warn_http">AVISO: \"http\" es inseguro. Por favor, use \"https\".</string>
<string name="settings_username">Nombre de usuario</string>
<string name="settings_password">Contraseña</string>
<string name="settings_password_unchanged">Contraseña (no cambiada)</string>
<string name="settings_password_check_description">Muestra si las credenciales son correctas.</string>
<string name="settings_submit">Conectar</string>
<string name="settings_submitting">Conectando &#8230;</string>
<string name="settings_note_mode">Modo de visualización para notas</string> <string name="settings_note_mode">Modo de visualización para notas</string>
<string name="settings_theme_title">Tema oscuro</string> <string name="settings_theme_title">Tema oscuro</string>
<string name="settings_font_title">Tipo de letra monoespaciado</string> <string name="settings_font_title">Tipo de letra monoespaciado</string>
<string name="settings_font_size">Tamaño de fuente</string> <string name="settings_font_size">Tamaño de fuente</string>
<string name="settings_wifi_only">Sincronizar solo sobre Wi-Fi</string> <string name="settings_wifi_only">Sincronizar solo sobre Wi-Fi</string>
<string name="settings_cert_category">Configuración de certificados</string>
<string name="settings_cert_trust_system">Confiar en los certificados del sistema</string>
<string name="settings_cert_trust_system_on">Se confiará en las autoridades de certificación —CAs— del sistema y añadidas por el usuario (recomendado)</string>
<string name="settings_cert_trust_system_off">No se confiará en las CAs del sistema y añadidas por el usuario</string>
<string name="settings_cert_reset">Restablecer almacenaje de certificados (marcados como fiables o no)</string>
<string name="settings_cert_reset_summary">Resetea todos los certificados personalizados en los que se había confiado</string>
<string name="settings_cert_reset_toast">Todos los certificados personalizados han sido eliminados</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Notas - Seguridad de la conexión</string>
<string name="trust_certificate_unknown_certificate_found">Notas ha encontrado un certificado desconocido. ¿Quiere confiar en él?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Conectando</string>
<string name="network_connected">Conectado</string>
<string name="network_disconnected">No hay redes disponibles</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Fallo en la sincronización: %1$s</string> <string name="error_sync">Fallo en la sincronización: %1$s</string>
<string name="error_invalid_login">Acceso inválido: %1$s</string>
<string name="error_json">¿Está la app de Notas activada en el servidor?</string> <string name="error_json">¿Está la app de Notas activada en el servidor?</string>
<string name="error_io">se ha perdido la conexión con el servidor</string>
<string name="error_no_network">no hay conexión a la red</string> <string name="error_no_network">no hay conexión a la red</string>
<string name="error_server">La URL o servidor tiene errores</string>
<string name="error_url_malformed">Dirección del servidor errónea</string>
<string name="error_username_password_invalid">Usuario o contraseña erróneos</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Configuración</string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versión</string> <string name="about_version_title">Versión</string>
@ -127,7 +92,6 @@
<string name="shortcut_create_long">Crear una nota nueva</string> <string name="shortcut_create_long">Crear una nota nueva</string>
<string name="pref_value_theme_light">Claro</string> <string name="pref_value_theme_light">Claro</string>
<string name="pref_value_theme_dark">Oscuro</string>
<string name="pref_value_font_normal">Normal</string> <string name="pref_value_font_normal">Normal</string>
<string name="pref_value_wifi_and_mobile">Sincronizar sobre Wi-Fi y datos móviles</string> <string name="pref_value_wifi_and_mobile">Sincronizar sobre Wi-Fi y datos móviles</string>
<string name="simple_error">Error</string> <string name="simple_error">Error</string>
@ -137,6 +101,14 @@
<string name="copied_to_clipboard">Copiado al portapapeles</string> <string name="copied_to_clipboard">Copiado al portapapeles</string>
<string name="pin_to_homescreen">Acoplar a la pantalla de inicio</string> <string name="pin_to_homescreen">Acoplar a la pantalla de inicio</string>
<string name="note_has_been_deleted">Esta nota ha sido borrada</string> <string name="note_has_been_deleted">Esta nota ha sido borrada</string>
<string name="add_account">Agregar cuenta</string>
<string name="category_music">Música</string>
<string name="category_movies">Películas</string>
<string name="category_movie">Película</string>
<string name="category_work">Trabajo</string>
<string name="account_already_imported">La cuenta ha ha sido importada</string>
<string name="no_notes_yet">Aún no hay notas</string>
<string name="no_notes_yet_description">rear una nota nueva</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">

View file

@ -2,89 +2,56 @@
<resources> <resources>
<string name="app_name">Oharrak</string> <string name="app_name">Oharrak</string>
<string name="no_notes">Ez dago oharrik</string> <string name="app_name_long">Nextcloud Oharrak</string>
<string name="label_all_notes">Ohar guztiak</string> <string name="label_all_notes">Ohar guztiak</string>
<string name="label_favorites">Gogokoak</string> <string name="label_favorites">Gogokoak</string>
<string name="action_create">Ohar berria</string> <string name="action_create">Ohar berria</string>
<string name="action_settings">Ezarpenak</string> <string name="action_settings">Ezarpenak</string>
<string name="action_trashbin">Ezabatutako oharrak</string> <string name="action_trashbin">Ezabatutako oharrak</string>
<string name="action_search">Bilatu</string> <string name="action_search">Bilatu</string>
<string name="action_create_save">Gorde</string>
<string name="simple_cancel">Utzi</string> <string name="simple_cancel">Utzi</string>
<string name="simple_edit">Editatu</string> <string name="simple_edit">Editatu</string>
<string name="action_edit_save">Gorde</string> <string name="action_edit_save">Gorde</string>
<string name="action_edit_saving">Gordetzen &#8230;</string>
<string name="action_edit_saved">Gordeta</string>
<string name="simple_about">Honi buruz</string> <string name="simple_about">Honi buruz</string>
<string name="simple_bold">Lodia</string> <string name="simple_bold">Lodia</string>
<string name="simple_link">Esteka</string> <string name="simple_link">Esteka</string>
<string name="simple_italic">Etzana</string> <string name="simple_italic">Etzana</string>
<string name="action_select_note">Oharra aukeratu </string>
<string name="action_note_deleted">Oharra ezabatua</string> <string name="action_note_deleted">Oharra ezabatua</string>
<string name="action_note_restored">Oharra berreskuratuta</string> <string name="action_note_restored">Oharra berreskuratuta</string>
<string name="action_undo">Desegin</string> <string name="action_undo">Desegin</string>
<string name="action_drawer_open">ireki nabigazioa</string> <string name="action_drawer_open">ireki nabigazioa</string>
<string name="action_drawer_close">itxi nabigazioa</string> <string name="action_drawer_close">itxi nabigazioa</string>
<string name="action_recent">Azkenak</string>
<string name="action_uncategorized">Kategoria gabe</string> <string name="action_uncategorized">Kategoria gabe</string>
<string name="menu_delete">Ezabatu</string> <string name="menu_delete">Ezabatu</string>
<string name="menu_change_category">Kategoria</string> <string name="menu_change_category">Kategoria</string>
<string name="menu_favorite">Gogokoa</string> <string name="menu_favorite">Gogokoa</string>
<string name="menu_preview">Aurreikusi</string> <string name="menu_preview">Aurreikusi</string>
<string name="menu_share">Partekatu</string> <string name="menu_share">Partekatu</string>
<string name="menu_about">Honi buruz</string>
<string name="change_category_title">Hautatu kategoria bat</string> <string name="change_category_title">Hautatu kategoria bat</string>
<string name="listview_updated_today">Gaur</string> <string name="listview_updated_today">Gaur</string>
<string name="listview_updated_yesterday">Atzo</string> <string name="listview_updated_yesterday">Atzo</string>
<string name="listview_updated_this_week">Aste honetan</string> <string name="listview_updated_this_week">Aste honetan</string>
<string name="listview_updated_last_week">Joan den astean</string>
<string name="listview_updated_this_month">Hilabete honetan</string> <string name="listview_updated_this_month">Hilabete honetan</string>
<string name="listview_updated_earlier">Lehenago</string> <string name="listview_updated_last_month">Joan den hilabetean</string>
<!-- Settings --> <!-- Settings -->
<string name="settings_server_settings">Kontua</string>
<string name="settings_url">Zerbitzariaren helbidea</string>
<string name="settings_url_check_description">Helbideari ping egin dakiokeen erakusten du.</string>
<string name="settings_url_warn_http">ABISUA: \"http\" ez da segurua. Mesedez, erabili \"https\".</string>
<string name="settings_username">Erabiltzaile izena</string>
<string name="settings_password">Pasahitza</string>
<string name="settings_password_unchanged">Pasahitza (aldatu gabea)</string>
<string name="settings_password_check_description">Kredentzialak zuzenak diren erakusten du.</string>
<string name="settings_submit">Konektatu</string>
<string name="settings_submitting">Konektatzen &#8230;</string>
<string name="settings_note_mode">Erakutsi oharren modua</string> <string name="settings_note_mode">Erakutsi oharren modua</string>
<string name="settings_theme_title">Gai iluna</string> <string name="settings_theme_title">Gai iluna</string>
<string name="settings_font_title">Zabalera bakarreko letra mota</string>
<string name="settings_font_size">Letra tamaina</string>
<string name="settings_wifi_only">Sinkronizatu wifi bidez bakarrik</string> <string name="settings_wifi_only">Sinkronizatu wifi bidez bakarrik</string>
<string name="settings_cert_category">Kudeatu ziurtagiriak</string>
<string name="settings_cert_trust_system">Fidatu sistemako ziurtagirietaz</string>
<string name="settings_cert_trust_system_on">Sistemako eta erabiltzaileak gehitutako ziurtagiriak fidagarritzat joko dira (aholkatua)</string>
<string name="settings_cert_trust_system_off">Sistemako eta erabiltzaileak gehitutako ziurtagiriak ez dira fidagarritzat joko</string>
<string name="settings_cert_reset">Leheneratu ziurtagiri (ez) fidagarriak</string>
<string name="settings_cert_reset_summary">Ziurtagiri pertsonalizatu guztien fidagarritasuna leheneratzen du</string>
<string name="settings_cert_reset_toast">Ziurtagiri pertsonalizatu guztiak garbitu dira</string>
<!-- Certificates --> <!-- Certificates -->
<string name="certificate_notification_connection_security">Oharrak - Konexioaren segurtasuna</string>
<string name="trust_certificate_unknown_certificate_found">Oharrak aplikazioak ziurtagiri ezezagun bat aurkitu du. Honetaz fidatu nahi duzu?</string>
<!-- Network --> <!-- Network -->
<string name="network_connecting">Konektatzen</string>
<string name="network_connected">Konektatuta</string>
<string name="network_disconnected">Sarea ez dago eskuragarri</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Sinkronizazioa huts egin du: %1$s</string> <string name="error_sync">Sinkronizazioa huts egin du: %1$s</string>
<string name="error_invalid_login">Login-a ez du balio: %1$s</string>
<string name="error_json">Oharrak aplikazioa zerbitzariak aktibatuta al dago?</string> <string name="error_json">Oharrak aplikazioa zerbitzariak aktibatuta al dago?</string>
<string name="error_io">Konexioa zerbitzariarekin ez dabil</string>
<string name="error_no_network">Ez dago sare-konexiorik</string> <string name="error_no_network">Ez dago sare-konexiorik</string>
<string name="error_server">URL/Zerbitzaria erroreak ditu</string>
<string name="error_url_malformed">Zerbitzari helbide okerra</string>
<string name="error_username_password_invalid">Erabiltzaile edo pasahitz okerra</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Ezarpenak</string>
<!-- About --> <!-- About -->
<string name="about_version_title">Bertsioa</string> <string name="about_version_title">Bertsioa</string>
@ -125,7 +92,6 @@
<string name="shortcut_create_long">Sortu ohar berria</string> <string name="shortcut_create_long">Sortu ohar berria</string>
<string name="pref_value_theme_light">Argia</string> <string name="pref_value_theme_light">Argia</string>
<string name="pref_value_theme_dark">Iluna</string>
<string name="pref_value_font_normal">Normala</string> <string name="pref_value_font_normal">Normala</string>
<string name="pref_value_wifi_and_mobile">Sinkronizatu wifi eta datu mugikorrekin</string> <string name="pref_value_wifi_and_mobile">Sinkronizatu wifi eta datu mugikorrekin</string>
<string name="simple_error">Errorea</string> <string name="simple_error">Errorea</string>
@ -133,6 +99,17 @@
<string name="simple_copy">Kopiatu</string> <string name="simple_copy">Kopiatu</string>
<string name="simple_exception">Salbuespena</string> <string name="simple_exception">Salbuespena</string>
<string name="copied_to_clipboard">Arbelera kopiatua</string> <string name="copied_to_clipboard">Arbelera kopiatua</string>
<string name="pin_to_homescreen">Hasierako pantailara egokitu</string>
<string name="note_has_been_deleted">Ohar hau ezabatu da</string>
<string name="add_account">Gehitu kontua</string>
<string name="category_music">Musika</string>
<string name="category_movies">Filmak</string>
<string name="category_movie">Filma</string>
<string name="category_work">Lana</string>
<string name="account_already_imported">Kontua dagoeneko inportatu da</string>
<string name="no_notes_yet">Ez dago oharrik</string>
<string name="no_notes_yet_description">Sakatu + botoia ohar berria sortzeko</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Ireki edizio moduan</item> <item>Ireki edizio moduan</item>
@ -140,6 +117,13 @@
<item>Gogoratu nire azken hautaketa</item> <item>Gogoratu nire azken hautaketa</item>
</string-array> </string-array>
<!-- Array: font size -->
<string-array name="fontSize_entries">
<item>Txikia</item>
<item>Ertaina</item>
<item>Handia</item>
</string-array>
<!-- Plurals --> <!-- Plurals -->
<plurals name="ab_selected"> <plurals name="ab_selected">
<item quantity="one">%d hautatuta</item> <item quantity="one">%d hautatuta</item>

View file

@ -2,77 +2,54 @@
<resources> <resources>
<string name="app_name">Muistiinpanot</string> <string name="app_name">Muistiinpanot</string>
<string name="no_notes">Ei muistiinpanoja</string>
<string name="label_all_notes">Kaikki muistiinpanot</string> <string name="label_all_notes">Kaikki muistiinpanot</string>
<string name="label_favorites">Suosikit</string> <string name="label_favorites">Suosikit</string>
<string name="action_create">Uusi muistiinpano</string> <string name="action_create">Uusi muistiinpano</string>
<string name="action_settings">Asetukset</string> <string name="action_settings">Asetukset</string>
<string name="action_trashbin">Poistetut muistiinpanot</string> <string name="action_trashbin">Poistetut muistiinpanot</string>
<string name="action_search">Etsi</string> <string name="action_search">Etsi</string>
<string name="action_create_save">Tallenna</string>
<string name="simple_cancel">Peruuta</string> <string name="simple_cancel">Peruuta</string>
<string name="simple_edit">Muokkaa</string> <string name="simple_edit">Muokkaa</string>
<string name="action_edit_save">Tallenna</string> <string name="action_edit_save">Tallenna</string>
<string name="action_edit_saving">Tallennetaan...</string>
<string name="action_edit_saved">Tallennettu</string>
<string name="simple_about">Tietoja</string> <string name="simple_about">Tietoja</string>
<string name="simple_bold">Lihavoitu</string> <string name="simple_bold">Lihavoitu</string>
<string name="simple_link">Linkki</string> <string name="simple_link">Linkki</string>
<string name="simple_italic">Kursivoitu</string> <string name="simple_italic">Kursivoitu</string>
<string name="action_select_note">Valitse muistiinpano</string>
<string name="action_note_deleted">Muistiinpano poistettu</string> <string name="action_note_deleted">Muistiinpano poistettu</string>
<string name="action_note_restored">Muistiinpano palautettu</string> <string name="action_note_restored">Muistiinpano palautettu</string>
<string name="action_undo">Kumoa</string> <string name="action_undo">Kumoa</string>
<string name="action_drawer_open">avaa navigaatio</string> <string name="action_drawer_open">avaa navigaatio</string>
<string name="action_drawer_close">sulje navigaatio</string> <string name="action_drawer_close">sulje navigaatio</string>
<string name="action_recent">Viimeisimmät</string>
<string name="action_uncategorized">Luokittelemattomat</string> <string name="action_uncategorized">Luokittelemattomat</string>
<string name="menu_delete">Poista</string> <string name="menu_delete">Poista</string>
<string name="menu_change_category">Luokka</string> <string name="menu_change_category">Luokka</string>
<string name="menu_favorite">Suosikki</string> <string name="menu_favorite">Suosikki</string>
<string name="menu_preview">Esikatselu</string> <string name="menu_preview">Esikatselu</string>
<string name="menu_share">Jaa</string> <string name="menu_share">Jaa</string>
<string name="menu_about">Tietoja</string>
<string name="change_category_title">Valitse luokka</string> <string name="change_category_title">Valitse luokka</string>
<string name="listview_updated_today">Tänään</string> <string name="listview_updated_today">Tänään</string>
<string name="listview_updated_yesterday">Eilen</string> <string name="listview_updated_yesterday">Eilen</string>
<string name="listview_updated_this_week">Tämä viikko</string> <string name="listview_updated_this_week">Tämä viikko</string>
<string name="listview_updated_last_week">Viime viikolla</string>
<string name="listview_updated_this_month">Tämä kuukausi</string> <string name="listview_updated_this_month">Tämä kuukausi</string>
<string name="listview_updated_earlier">Aikaisemmat</string> <string name="listview_updated_last_month">Viime kuussa</string>
<!-- Settings --> <!-- Settings -->
<string name="settings_server_settings">Tili</string>
<string name="settings_url">Palvelimen osoite</string>
<string name="settings_url_warn_http">VAROITUS: \"http\" on suojaamaton. Käytä \"https\"-yhteyttä.</string>
<string name="settings_username">Käyttäjätunnus</string>
<string name="settings_password">Salasana</string>
<string name="settings_password_unchanged">Salasana (ei muutettu)</string>
<string name="settings_password_check_description">Näyttää ovatko tilitiedot oikein.</string>
<string name="settings_submit">Yhdistä</string>
<string name="settings_submitting">Yhdistetään...</string>
<string name="settings_note_mode">Muistiinpanojen esitystapa</string> <string name="settings_note_mode">Muistiinpanojen esitystapa</string>
<string name="settings_theme_title">Tumma teema</string> <string name="settings_theme_title">Tumma teema</string>
<string name="settings_font_title">Tasalevyinen fontti</string> <string name="settings_font_title">Tasalevyinen fontti</string>
<string name="settings_font_size">Fontin koko</string>
<string name="settings_wifi_only">Synkronoi vain wifi-yhteydellä</string> <string name="settings_wifi_only">Synkronoi vain wifi-yhteydellä</string>
<string name="settings_cert_category">Hallitse varmenteita</string>
<string name="settings_cert_trust_system">Luota järjestelmävarmenteisiin</string> <!-- Certificates -->
<!-- Network --> <!-- Network -->
<string name="network_connecting">Yhdistetään</string>
<string name="network_connected">Yhdistetty</string>
<string name="network_disconnected">Verkkoa ei ole saatavilla</string>
<!-- Error --> <!-- Error -->
<string name="error_sync">Synkronointi epäonnistui: %1$s</string> <string name="error_sync">Synkronointi epäonnistui: %1$s</string>
<string name="error_invalid_login">Virheellinen kirjautuminen: %1$s</string>
<string name="error_io">palvelinyhteys on rikki</string>
<string name="error_no_network">ei verkkoyhteyttä</string> <string name="error_no_network">ei verkkoyhteyttä</string>
<string name="error_url_malformed">Virheellinen palvelimen osoite</string>
<string name="error_username_password_invalid">Väärä käyttäjätunnus tai salasana</string>
<!-- Snackbar Actions -->
<string name="snackbar_settings">Asetukset</string>
<!-- About --> <!-- About -->
<string name="about_version_title">Versio</string> <string name="about_version_title">Versio</string>
@ -106,8 +83,19 @@
<string name="shortcut_create_long">Luo uusi muistiinpano</string> <string name="shortcut_create_long">Luo uusi muistiinpano</string>
<string name="pref_value_theme_light">Vaalea</string> <string name="pref_value_theme_light">Vaalea</string>
<string name="pref_value_theme_dark">Tumma</string> <string name="pref_value_font_normal">Normaali</string>
<string name="pref_value_wifi_and_mobile">Synkronoi wifi- ja mobiilidatayhteydellä</string> <string name="pref_value_wifi_and_mobile">Synkronoi wifi- ja mobiilidatayhteydellä</string>
<string name="simple_error">Virhe</string>
<string name="simple_close">Sulje</string>
<string name="simple_copy">Kopioi</string>
<string name="simple_exception">Poikkeus</string>
<string name="copied_to_clipboard">Kopioitu leikepöydälle</string>
<string name="pin_to_homescreen">Kiinnitä kotinäyttöön</string>
<string name="add_account">Lisää tili</string>
<string name="category_music">Musiikki</string>
<string name="category_movies">Elokuvat</string>
<string name="category_work">Työ</string>
<string name="no_notes_yet">Ei muistiinpanoja</string>
<!-- Array: note modes --> <!-- Array: note modes -->
<string-array name="noteMode_entries"> <string-array name="noteMode_entries">
<item>Avaa muokkaustilassa</item> <item>Avaa muokkaustilassa</item>
@ -115,6 +103,13 @@
<item>Muista viimeisin valintani</item> <item>Muista viimeisin valintani</item>
</string-array> </string-array>
<!-- Array: font size -->
<string-array name="fontSize_entries">
<item>Pieni</item>
<item>Normaali</item>
<item>Suuri</item>
</string-array>
<!-- Plurals --> <!-- Plurals -->
<plurals name="ab_selected"> <plurals name="ab_selected">
<item quantity="one">%d valittu</item> <item quantity="one">%d valittu</item>

Some files were not shown because too many files have changed in this diff Show more