mirror of
https://github.com/PhilKes/NotallyX.git
synced 2025-06-30 13:19:54 +00:00
Compare commits
No commits in common. "main" and "v7.3.1" have entirely different histories.
51 changed files with 40441 additions and 33553 deletions
27
CHANGELOG.md
27
CHANGELOG.md
|
@ -1,32 +1,5 @@
|
|||
# Changelog
|
||||
|
||||
## [v7.4.0](https://github.com/PhilKes/NotallyX/tree/v7.4.0) (2025-04-18)
|
||||
|
||||
[Full Changelog](https://github.com/PhilKes/NotallyX/compare/v7.3.1...v7.4.0)
|
||||
|
||||
### Added Features
|
||||
|
||||
- Don't force capitalization when adding a label [\#532](https://github.com/PhilKes/NotallyX/issues/532)
|
||||
- Add a screen protection against screenshot attempts [\#386](https://github.com/PhilKes/NotallyX/issues/386)
|
||||
|
||||
### Fixed Bugs
|
||||
|
||||
- Share pure text note error [\#544](https://github.com/PhilKes/NotallyX/issues/544)
|
||||
- Crash when deleting checked items in a list [\#539](https://github.com/PhilKes/NotallyX/issues/539)
|
||||
- Keyboard don't open after closing it on Android 7 [\#537](https://github.com/PhilKes/NotallyX/issues/537)
|
||||
- Unable to open links before changing view mode [\#527](https://github.com/PhilKes/NotallyX/issues/527)
|
||||
- Reminder popup cut on small screens [\#522](https://github.com/PhilKes/NotallyX/issues/522)
|
||||
- Auto Backup failed [\#514](https://github.com/PhilKes/NotallyX/issues/514)
|
||||
|
||||
## [v7.3.1](https://github.com/PhilKes/NotallyX/tree/v7.3.1) (2025-04-08)
|
||||
|
||||
[Full Changelog](https://github.com/PhilKes/NotallyX/compare/v7.3.0...v7.3.1)
|
||||
|
||||
### Fixed Bugs
|
||||
|
||||
- Button to close note search doesn't work [\#519](https://github.com/PhilKes/NotallyX/issues/519)
|
||||
- app crashes when pressing label [\#517](https://github.com/PhilKes/NotallyX/issues/517)
|
||||
|
||||
## [v7.3.0](https://github.com/PhilKes/NotallyX/tree/v7.3.0) (2025-04-07)
|
||||
|
||||
[Full Changelog](https://github.com/PhilKes/NotallyX/compare/v7.2.1...v7.3.0)
|
||||
|
|
|
@ -190,7 +190,7 @@ dependencies {
|
|||
implementation("androidx.security:security-crypto:1.1.0-alpha06")
|
||||
implementation("androidx.sqlite:sqlite-ktx:2.4.0")
|
||||
implementation("androidx.work:work-runtime:2.9.1")
|
||||
implementation("androidx.biometric:biometric:1.1.0")
|
||||
|
||||
implementation("cat.ereza:customactivityoncrash:2.4.0")
|
||||
implementation("com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0")
|
||||
implementation("com.github.bumptech.glide:glide:4.15.1")
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -77,21 +77,6 @@
|
|||
<data android:mimeType="*/*" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="file" android:mimeType="text/*" />
|
||||
<data android:scheme="content" android:mimeType="text/*" />
|
||||
|
||||
<data android:scheme="file" android:mimeType="application/json" />
|
||||
<data android:scheme="content" android:mimeType="application/json" />
|
||||
|
||||
<data android:scheme="file" android:mimeType="application/xml" />
|
||||
<data android:scheme="content" android:mimeType="application/xml" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".presentation.activity.note.ViewImageActivity" />
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
package com.philkes.notallyx
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import com.philkes.notallyx.presentation.setEnabledSecureFlag
|
||||
import com.philkes.notallyx.presentation.view.misc.NotNullLiveData
|
||||
import com.philkes.notallyx.presentation.viewmodel.preference.BiometricLock
|
||||
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
|
||||
|
@ -36,7 +33,7 @@ import kotlinx.coroutines.MainScope
|
|||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class NotallyXApplication : Application(), Application.ActivityLifecycleCallbacks {
|
||||
class NotallyXApplication : Application() {
|
||||
|
||||
private lateinit var biometricLockObserver: Observer<BiometricLock>
|
||||
private lateinit var preferences: NotallyXPreferences
|
||||
|
@ -46,7 +43,6 @@ class NotallyXApplication : Application(), Application.ActivityLifecycleCallback
|
|||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
registerActivityLifecycleCallbacks(this)
|
||||
if (isTestRunner()) return
|
||||
preferences = NotallyXPreferences.getInstance(this)
|
||||
if (preferences.useDynamicColors.value) {
|
||||
|
@ -70,7 +66,7 @@ class NotallyXApplication : Application(), Application.ActivityLifecycleCallback
|
|||
)
|
||||
}
|
||||
if (oldTheme != null) {
|
||||
WidgetProvider.updateWidgets(this, locked = locked.value)
|
||||
WidgetProvider.updateWidgets(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,20 +168,4 @@ class NotallyXApplication : Application(), Application.ActivityLifecycleCallback
|
|||
return Build.FINGERPRINT.equals("robolectric", ignoreCase = true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
|
||||
activity.setEnabledSecureFlag(preferences.secureFlag.value)
|
||||
}
|
||||
|
||||
override fun onActivityStarted(activity: Activity) {}
|
||||
|
||||
override fun onActivityResumed(activity: Activity) {}
|
||||
|
||||
override fun onActivityPaused(activity: Activity) {}
|
||||
|
||||
override fun onActivityStopped(activity: Activity) {}
|
||||
|
||||
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
|
||||
|
||||
override fun onActivityDestroyed(activity: Activity) {}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ interface BaseNoteDao {
|
|||
@Query("SELECT id, reminders FROM BaseNote WHERE reminders IS NOT NULL AND reminders != '[]'")
|
||||
suspend fun getAllReminders(): List<NoteIdReminder>
|
||||
|
||||
@Query("SELECT color FROM BaseNote WHERE id = :id ") fun getColorOfNote(id: Long): String?
|
||||
@Query("SELECT color FROM BaseNote WHERE id = :id ") fun getColorOfNote(id: Long): String
|
||||
|
||||
@Query(
|
||||
"SELECT id, title, type, reminders FROM BaseNote WHERE reminders IS NOT NULL AND reminders != '[]'"
|
||||
|
|
|
@ -122,7 +122,7 @@ fun String.applySpans(representations: List<SpanRepresentation>): Editable {
|
|||
->
|
||||
try {
|
||||
if (bold) {
|
||||
editable.setSpan(createBoldSpan(), start, end)
|
||||
editable.setSpan(StyleSpan(Typeface.BOLD), start, end)
|
||||
}
|
||||
if (italic) {
|
||||
editable.setSpan(StyleSpan(Typeface.ITALIC), start, end)
|
||||
|
@ -144,13 +144,6 @@ fun String.applySpans(representations: List<SpanRepresentation>): Editable {
|
|||
return editable
|
||||
}
|
||||
|
||||
fun createBoldSpan() =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
StyleSpan(Typeface.BOLD, 700)
|
||||
} else {
|
||||
StyleSpan(Typeface.BOLD)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts or removes spans based on the selection range.
|
||||
*
|
||||
|
@ -247,11 +240,7 @@ fun ViewGroup.addIconButton(
|
|||
val view =
|
||||
ImageButton(ContextThemeWrapper(context, R.style.AppTheme)).apply {
|
||||
setImageResource(drawable)
|
||||
val titleText = context.getString(title)
|
||||
contentDescription = titleText
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
tooltipText = titleText
|
||||
}
|
||||
contentDescription = context.getString(title)
|
||||
val outValue = TypedValue()
|
||||
context.theme.resolveAttribute(android.R.attr.actionBarItemBackground, outValue, true)
|
||||
setBackgroundResource(outValue.resourceId)
|
||||
|
@ -538,17 +527,6 @@ fun Activity.checkAlarmPermission(
|
|||
} else onSuccess()
|
||||
}
|
||||
|
||||
fun Activity.setEnabledSecureFlag(enabled: Boolean) {
|
||||
if (enabled) {
|
||||
window.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_SECURE,
|
||||
WindowManager.LayoutParams.FLAG_SECURE,
|
||||
)
|
||||
} else {
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||
}
|
||||
}
|
||||
|
||||
fun Fragment.displayEditLabelDialog(
|
||||
oldValue: String,
|
||||
model: BaseNoteModel,
|
||||
|
|
|
@ -64,10 +64,7 @@ abstract class LockedActivity<T : ViewBinding> : AppCompatActivity() {
|
|||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
if (
|
||||
preferences.biometricLock.value == BiometricLock.ENABLED &&
|
||||
notallyXApplication.locked.value
|
||||
) {
|
||||
if (preferences.biometricLock.value == BiometricLock.ENABLED) {
|
||||
hide()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,7 +237,6 @@ abstract class NotallyFragment : Fragment(), ItemListener {
|
|||
maxLines.value,
|
||||
maxTitle.value,
|
||||
labelTagsHiddenInOverview.value,
|
||||
imagesHiddenInOverview.value,
|
||||
),
|
||||
model.imageRoot,
|
||||
this@NotallyFragment,
|
||||
|
|
|
@ -6,7 +6,6 @@ import android.view.View
|
|||
import androidx.core.os.BundleCompat
|
||||
import androidx.core.view.isVisible
|
||||
import com.philkes.notallyx.R
|
||||
import com.philkes.notallyx.data.model.BaseNote
|
||||
import com.philkes.notallyx.data.model.Folder
|
||||
|
||||
class SearchFragment : NotallyFragment() {
|
||||
|
@ -45,9 +44,6 @@ class SearchFragment : NotallyFragment() {
|
|||
isVisible = true
|
||||
}
|
||||
} else binding?.ChipGroup?.isVisible = false
|
||||
getObservable().observe(viewLifecycleOwner) { items ->
|
||||
model.actionMode.updateSelected(items?.filterIsInstance<BaseNote>()?.map { it.id })
|
||||
}
|
||||
}
|
||||
|
||||
override fun getBackground() = R.drawable.search
|
||||
|
|
|
@ -33,7 +33,6 @@ import com.philkes.notallyx.databinding.DialogTextInputBinding
|
|||
import com.philkes.notallyx.databinding.FragmentSettingsBinding
|
||||
import com.philkes.notallyx.presentation.activity.main.MainActivity
|
||||
import com.philkes.notallyx.presentation.setCancelButton
|
||||
import com.philkes.notallyx.presentation.setEnabledSecureFlag
|
||||
import com.philkes.notallyx.presentation.setupImportProgressDialog
|
||||
import com.philkes.notallyx.presentation.setupProgressDialog
|
||||
import com.philkes.notallyx.presentation.showAndFocus
|
||||
|
@ -351,17 +350,6 @@ class SettingsFragment : Fragment() {
|
|||
model.savePreference(labelTagsHiddenInOverview, enabled)
|
||||
}
|
||||
}
|
||||
imagesHiddenInOverview.observe(viewLifecycleOwner) { value ->
|
||||
binding.ImagesHiddenInOverview.setup(
|
||||
imagesHiddenInOverview,
|
||||
value,
|
||||
requireContext(),
|
||||
layoutInflater,
|
||||
R.string.images_hidden_in_overview,
|
||||
) { enabled ->
|
||||
model.savePreference(imagesHiddenInOverview, enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -604,14 +592,6 @@ class SettingsFragment : Fragment() {
|
|||
model.savePreference(backupPassword, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
secureFlag.observe(viewLifecycleOwner) { value ->
|
||||
binding.SecureFlag.setup(secureFlag, value, requireContext(), layoutInflater) { newValue
|
||||
->
|
||||
model.savePreference(secureFlag, newValue)
|
||||
activity?.setEnabledSecureFlag(newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun NotallyXPreferences.setupSettings(binding: FragmentSettingsBinding) {
|
||||
|
|
|
@ -188,15 +188,14 @@ abstract class EditActivity(private val type: Type) :
|
|||
if (persistedId == null || notallyModel.originalNote == null) {
|
||||
notallyModel.setState(id)
|
||||
}
|
||||
if (notallyModel.isNewNote) {
|
||||
when (intent.action) {
|
||||
Intent.ACTION_SEND,
|
||||
Intent.ACTION_SEND_MULTIPLE -> handleSharedNote()
|
||||
Intent.ACTION_VIEW -> handleViewNote()
|
||||
else ->
|
||||
intent.getStringExtra(EXTRA_DISPLAYED_LABEL)?.let {
|
||||
notallyModel.setLabels(listOf(it))
|
||||
}
|
||||
if (
|
||||
notallyModel.isNewNote &&
|
||||
intent.action in setOf(Intent.ACTION_SEND, Intent.ACTION_SEND_MULTIPLE)
|
||||
) {
|
||||
handleSharedNote()
|
||||
} else if (notallyModel.isNewNote) {
|
||||
intent.getStringExtra(EXTRA_DISPLAYED_LABEL)?.let {
|
||||
notallyModel.setLabels(listOf(it))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -552,7 +551,7 @@ abstract class EditActivity(private val type: Type) :
|
|||
removeAllViews()
|
||||
|
||||
addToggleViewMode()
|
||||
addIconButton(R.string.tap_for_more_options, R.drawable.more_vert, marginStart = 0) {
|
||||
addIconButton(R.string.more, R.drawable.more_vert, marginStart = 0) {
|
||||
MoreNoteBottomSheet(
|
||||
this@EditActivity,
|
||||
createNoteTypeActions() + createFolderActions(),
|
||||
|
@ -633,7 +632,6 @@ abstract class EditActivity(private val type: Type) :
|
|||
}
|
||||
|
||||
private fun convertTo(type: Type) {
|
||||
updateModel()
|
||||
lifecycleScope.launch {
|
||||
notallyModel.convertTo(type)
|
||||
val intent =
|
||||
|
@ -657,23 +655,12 @@ abstract class EditActivity(private val type: Type) :
|
|||
notallyModel.title = text.trim().toString()
|
||||
}
|
||||
notallyModel.viewMode.observe(this) { value ->
|
||||
toggleViewMode.apply {
|
||||
setImageResource(
|
||||
when (value) {
|
||||
NoteViewMode.READ_ONLY -> R.drawable.edit
|
||||
else -> R.drawable.visibility
|
||||
}
|
||||
)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
tooltipText =
|
||||
getString(
|
||||
when (value) {
|
||||
NoteViewMode.READ_ONLY -> R.string.edit
|
||||
else -> R.string.read_only
|
||||
}
|
||||
)
|
||||
toggleViewMode.setImageResource(
|
||||
when (value) {
|
||||
NoteViewMode.READ_ONLY -> R.drawable.edit
|
||||
else -> R.drawable.visibility
|
||||
}
|
||||
}
|
||||
)
|
||||
value?.let { toggleCanEdit(it) }
|
||||
}
|
||||
}
|
||||
|
@ -758,26 +745,6 @@ abstract class EditActivity(private val type: Type) :
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleViewNote() {
|
||||
val text =
|
||||
intent.data?.let { uri ->
|
||||
contentResolver.openInputStream(uri)?.use { inputStream ->
|
||||
inputStream.bufferedReader().readText()
|
||||
}
|
||||
?: run {
|
||||
showToast(R.string.cant_load_file)
|
||||
null
|
||||
}
|
||||
} ?: intent.getStringExtra(Intent.EXTRA_TEXT)
|
||||
val title = intent.getStringExtra(Intent.EXTRA_SUBJECT)
|
||||
if (text != null) {
|
||||
notallyModel.body = Editable.Factory.getInstance().newEditable(text)
|
||||
}
|
||||
if (title != null) {
|
||||
notallyModel.title = title
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(24)
|
||||
override fun recordAudio() {
|
||||
val permission = Manifest.permission.RECORD_AUDIO
|
||||
|
@ -1095,9 +1062,7 @@ abstract class EditActivity(private val type: Type) :
|
|||
colorInt = extractColor(notallyModel.color)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
window.statusBarColor = colorInt
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||
window.navigationBarColor = colorInt
|
||||
}
|
||||
window.navigationBarColor = colorInt
|
||||
window.setLightStatusAndNavBar(colorInt.isLightColor())
|
||||
}
|
||||
binding.apply {
|
||||
|
|
|
@ -105,7 +105,7 @@ class EditListActivity : EditActivity(Type.LIST), MoreListActions {
|
|||
binding.BottomAppBarRight.apply {
|
||||
removeAllViews()
|
||||
addToggleViewMode()
|
||||
addIconButton(R.string.tap_for_more_options, R.drawable.more_vert, marginStart = 0) {
|
||||
addIconButton(R.string.more, R.drawable.more_vert, marginStart = 0) {
|
||||
MoreListBottomSheet(
|
||||
this@EditListActivity,
|
||||
createNoteTypeActions() + createFolderActions(),
|
||||
|
|
|
@ -40,7 +40,6 @@ import com.philkes.notallyx.presentation.activity.note.PickNoteActivity.Companio
|
|||
import com.philkes.notallyx.presentation.activity.note.PickNoteActivity.Companion.EXTRA_PICKED_NOTE_TYPE
|
||||
import com.philkes.notallyx.presentation.add
|
||||
import com.philkes.notallyx.presentation.addIconButton
|
||||
import com.philkes.notallyx.presentation.createBoldSpan
|
||||
import com.philkes.notallyx.presentation.dp
|
||||
import com.philkes.notallyx.presentation.hideKeyboard
|
||||
import com.philkes.notallyx.presentation.setControlsContrastColorForAllViews
|
||||
|
@ -69,6 +68,8 @@ class EditNoteActivity : EditActivity(Type.NOTE), AddNoteActions {
|
|||
override fun configureUI() {
|
||||
binding.EnterTitle.setOnNextAction { binding.EnterBody.requestFocus() }
|
||||
|
||||
setupEditor()
|
||||
|
||||
if (notallyModel.isNewNote) {
|
||||
binding.EnterBody.requestFocus()
|
||||
}
|
||||
|
@ -82,13 +83,13 @@ class EditNoteActivity : EditActivity(Type.NOTE), AddNoteActions {
|
|||
|
||||
override fun toggleCanEdit(mode: NoteViewMode) {
|
||||
super.toggleCanEdit(mode)
|
||||
setupEditor()
|
||||
textFormatMenu.isVisible = mode == NoteViewMode.EDIT
|
||||
when {
|
||||
mode == NoteViewMode.EDIT -> showKeyboard(binding.EnterBody)
|
||||
binding.EnterBody.isFocused -> hideKeyboard(binding.EnterBody)
|
||||
}
|
||||
binding.EnterBody.setCanEdit(mode == NoteViewMode.EDIT)
|
||||
setupEditor()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
|
@ -213,7 +214,7 @@ class EditNoteActivity : EditActivity(Type.NOTE), AddNoteActions {
|
|||
0,
|
||||
showAsAction = MenuItem.SHOW_AS_ACTION_NEVER,
|
||||
) {
|
||||
binding.EnterBody.applySpan(createBoldSpan())
|
||||
binding.EnterBody.applySpan(StyleSpan(Typeface.BOLD))
|
||||
mode?.finish()
|
||||
}
|
||||
add(
|
||||
|
|
|
@ -52,7 +52,6 @@ open class PickNoteActivity : LockedActivity<ActivityPickNoteBinding>(), ItemLis
|
|||
maxLines.value,
|
||||
maxTitle.value,
|
||||
labelTagsHiddenInOverview.value,
|
||||
imagesHiddenInOverview.value,
|
||||
),
|
||||
application.getExternalImagesDirectory(),
|
||||
this@PickNoteActivity,
|
||||
|
|
|
@ -45,7 +45,6 @@ data class BaseNoteVHPreferences(
|
|||
val maxLines: Int,
|
||||
val maxTitleLines: Int,
|
||||
val hideLabels: Boolean,
|
||||
val hideImages: Boolean,
|
||||
)
|
||||
|
||||
class BaseNoteVH(
|
||||
|
@ -210,8 +209,9 @@ class BaseNoteVH(
|
|||
}
|
||||
|
||||
private fun setImages(images: List<FileAttachment>, mediaRoot: File?) {
|
||||
|
||||
binding.apply {
|
||||
if (images.isNotEmpty() && !preferences.hideImages) {
|
||||
if (images.isNotEmpty()) {
|
||||
ImageView.visibility = VISIBLE
|
||||
Message.visibility = GONE
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.philkes.notallyx.presentation.view.misc
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.text.method.KeyListener
|
||||
|
@ -9,7 +8,6 @@ import android.util.AttributeSet
|
|||
import android.view.inputmethod.InputMethodManager
|
||||
import androidx.appcompat.widget.AppCompatEditText
|
||||
import com.philkes.notallyx.presentation.clone
|
||||
import com.philkes.notallyx.presentation.showKeyboard
|
||||
|
||||
open class EditTextWithWatcher(context: Context, attrs: AttributeSet) :
|
||||
AppCompatEditText(context, attrs) {
|
||||
|
@ -44,19 +42,6 @@ open class EditTextWithWatcher(context: Context, attrs: AttributeSet) :
|
|||
isFocusable = value
|
||||
isFocusableInTouchMode = value
|
||||
setTextIsSelectable(true)
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) {
|
||||
setOnClickListener {
|
||||
if (value) {
|
||||
context.showKeyboard(this)
|
||||
}
|
||||
}
|
||||
setOnFocusChangeListener { v, hasFocus ->
|
||||
if (hasFocus && value) {
|
||||
context.showKeyboard(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
|
|
|
@ -8,7 +8,6 @@ import android.text.style.TypefaceSpan
|
|||
import android.text.style.URLSpan
|
||||
import androidx.annotation.ColorInt
|
||||
import com.philkes.notallyx.R
|
||||
import com.philkes.notallyx.presentation.createBoldSpan
|
||||
import com.philkes.notallyx.presentation.view.misc.StylableEditTextWithHistory
|
||||
|
||||
class TextFormattingAdapter(
|
||||
|
@ -36,7 +35,7 @@ class TextFormattingAdapter(
|
|||
private val bold: Toggle =
|
||||
Toggle(R.string.bold, R.drawable.format_bold, false) {
|
||||
if (!it.checked) {
|
||||
editText.applySpan(createBoldSpan())
|
||||
editText.applySpan(StyleSpan(Typeface.BOLD))
|
||||
} else {
|
||||
editText.clearFormatting(type = StylableEditTextWithHistory.TextStyleType.BOLD)
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@ import com.philkes.notallyx.data.model.ListItem
|
|||
import com.philkes.notallyx.data.model.deepCopy
|
||||
import com.philkes.notallyx.data.model.findChild
|
||||
import com.philkes.notallyx.data.model.plus
|
||||
import com.philkes.notallyx.data.model.shouldParentBeChecked
|
||||
import com.philkes.notallyx.data.model.shouldParentBeUnchecked
|
||||
import com.philkes.notallyx.utils.filter
|
||||
import com.philkes.notallyx.utils.forEach
|
||||
import com.philkes.notallyx.utils.indices
|
||||
|
@ -151,20 +149,9 @@ fun <R> List<R>.getOrNull(index: Int) = if (lastIndex >= index) this[index] else
|
|||
fun Collection<ListItem>.init(resetIds: Boolean = true): List<ListItem> {
|
||||
val initializedItems = deepCopy()
|
||||
initList(initializedItems, resetIds)
|
||||
checkBrokenList(initializedItems)
|
||||
return initializedItems
|
||||
}
|
||||
|
||||
private fun checkBrokenList(list: List<ListItem>) {
|
||||
list.forEach { listItem ->
|
||||
if (listItem.shouldParentBeChecked()) {
|
||||
listItem.checked = true
|
||||
} else if (listItem.shouldParentBeUnchecked()) {
|
||||
listItem.checked = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initList(list: List<ListItem>, resetIds: Boolean) {
|
||||
if (resetIds) {
|
||||
list.forEachIndexed { index, item -> item.id = index }
|
||||
|
@ -263,7 +250,7 @@ fun SortedList<ListItem>.findParentsByChecked(checked: Boolean): List<ListItem>
|
|||
fun SortedList<ListItem>.deleteCheckedItems() {
|
||||
mapIndexed { index, listItem -> Pair(index, listItem) }
|
||||
.filter { it.second.checked }
|
||||
.sortedBy { !it.second.isChild }
|
||||
.sortedBy { it.second.isChild }
|
||||
.forEach { remove(it.second) }
|
||||
}
|
||||
|
||||
|
|
|
@ -163,7 +163,6 @@ class ListItemVH(
|
|||
binding.Content.descendantFocusability = ViewGroup.FOCUS_BLOCK_DESCENDANTS
|
||||
}
|
||||
setCanEdit(viewMode == NoteViewMode.EDIT)
|
||||
isFocusable = !item.checked
|
||||
when (viewMode) {
|
||||
NoteViewMode.EDIT -> {
|
||||
setOnClickListener(null)
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.net.toUri
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
|
@ -335,7 +336,7 @@ class BaseNoteModel(private val app: Application) : AndroidViewModel(app) {
|
|||
fun importZipBackup(uri: Uri, password: String) {
|
||||
val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
|
||||
app.log(TAG, throwable = throwable)
|
||||
app.showToast("${app.getString(R.string.invalid_backup)}: ${throwable.message}")
|
||||
app.showToast(R.string.invalid_backup)
|
||||
}
|
||||
|
||||
val backupDir = app.getBackupDir()
|
||||
|
@ -347,7 +348,7 @@ class BaseNoteModel(private val app: Application) : AndroidViewModel(app) {
|
|||
fun importXmlBackup(uri: Uri) {
|
||||
val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
|
||||
app.log(TAG, throwable = throwable)
|
||||
app.showToast("${app.getString(R.string.invalid_backup)}: ${throwable.message}")
|
||||
app.showToast(R.string.invalid_backup)
|
||||
}
|
||||
|
||||
viewModelScope.launch(exceptionHandler) {
|
||||
|
@ -365,15 +366,18 @@ class BaseNoteModel(private val app: Application) : AndroidViewModel(app) {
|
|||
|
||||
fun importFromOtherApp(uri: Uri, importSource: ImportSource) {
|
||||
val database = NotallyDatabase.getDatabase(app, observePreferences = false).value
|
||||
val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
|
||||
app.log(TAG, throwable = throwable)
|
||||
if (throwable is ImportException) {
|
||||
app.showToast(throwable.textResId)
|
||||
} else {
|
||||
app.showToast("${app.getString(R.string.invalid_backup)}: ${throwable.message}")
|
||||
}
|
||||
}
|
||||
|
||||
val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
|
||||
Toast.makeText(
|
||||
app,
|
||||
if (throwable is ImportException) {
|
||||
throwable.textResId
|
||||
} else R.string.invalid_backup,
|
||||
Toast.LENGTH_LONG,
|
||||
)
|
||||
.show()
|
||||
app.log(TAG, throwable = throwable)
|
||||
}
|
||||
viewModelScope.launch(exceptionHandler) {
|
||||
val importedNotes =
|
||||
withContext(Dispatchers.IO) {
|
||||
|
|
|
@ -84,13 +84,6 @@ class NotallyXPreferences private constructor(private val context: Context) {
|
|||
false,
|
||||
R.string.labels_hidden_in_overview_title,
|
||||
)
|
||||
val imagesHiddenInOverview =
|
||||
BooleanPreference(
|
||||
"imagesHiddenInOverview",
|
||||
preferences,
|
||||
false,
|
||||
R.string.images_hidden_in_overview_title,
|
||||
)
|
||||
val maxLabels =
|
||||
IntPreference(
|
||||
"maxLabelsInNavigation",
|
||||
|
@ -142,8 +135,6 @@ class NotallyXPreferences private constructor(private val context: Context) {
|
|||
val fallbackDatabaseEncryptionKey by lazy {
|
||||
ByteArrayPreference("fallback_database_encryption_key", encryptedPreferences, ByteArray(0))
|
||||
}
|
||||
val secureFlag =
|
||||
BooleanPreference("secureFlag", preferences, false, R.string.disallow_screenshots)
|
||||
|
||||
val dataInPublicFolder =
|
||||
BooleanPreference("dataOnExternalStorage", preferences, false, R.string.data_in_public)
|
||||
|
@ -232,7 +223,6 @@ class NotallyXPreferences private constructor(private val context: Context) {
|
|||
maxItems,
|
||||
maxLines,
|
||||
maxTitle,
|
||||
secureFlag,
|
||||
labelsHidden,
|
||||
labelTagsHiddenInOverview,
|
||||
maxLabels,
|
||||
|
@ -240,7 +230,6 @@ class NotallyXPreferences private constructor(private val context: Context) {
|
|||
backupPassword,
|
||||
backupOnSave,
|
||||
autoSaveAfterIdleTime,
|
||||
imagesHiddenInOverview,
|
||||
)
|
||||
.forEach { it.refresh() }
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import android.net.Uri
|
|||
import android.os.Build
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.philkes.notallyx.NotallyXApplication
|
||||
import com.philkes.notallyx.R
|
||||
import com.philkes.notallyx.data.NotallyDatabase
|
||||
import com.philkes.notallyx.data.dao.BaseNoteDao
|
||||
|
@ -43,10 +42,9 @@ class WidgetProvider : AppWidgetProvider() {
|
|||
super.onReceive(context, intent)
|
||||
when (intent.action) {
|
||||
ACTION_NOTES_MODIFIED -> {
|
||||
val app = context.applicationContext as NotallyXApplication
|
||||
val noteIds = intent.getLongArrayExtra(EXTRA_MODIFIED_NOTES)
|
||||
if (noteIds != null) {
|
||||
updateWidgets(context, noteIds, locked = app.locked.value)
|
||||
updateWidgets(context, noteIds)
|
||||
}
|
||||
}
|
||||
ACTION_OPEN_NOTE -> openActivity(context, intent, EditNoteActivity::class.java)
|
||||
|
@ -87,8 +85,7 @@ class WidgetProvider : AppWidgetProvider() {
|
|||
baseNoteDao.updateChecked(noteId, childrenPositions + position, checked!!)
|
||||
}
|
||||
} finally {
|
||||
val app = context.applicationContext as NotallyXApplication
|
||||
updateWidgets(context, longArrayOf(noteId), locked = app.locked.value)
|
||||
updateWidgets(context, longArrayOf(noteId))
|
||||
pendingResult.finish()
|
||||
}
|
||||
}
|
||||
|
@ -138,19 +135,19 @@ class WidgetProvider : AppWidgetProvider() {
|
|||
appWidgetManager: AppWidgetManager,
|
||||
appWidgetIds: IntArray,
|
||||
) {
|
||||
val app = context.applicationContext as NotallyXApplication
|
||||
val app = context.applicationContext as Application
|
||||
val preferences = NotallyXPreferences.getInstance(app)
|
||||
|
||||
appWidgetIds.forEach { id ->
|
||||
val noteId = preferences.getWidgetData(id)
|
||||
val noteType = preferences.getWidgetNoteType(id) ?: return
|
||||
updateWidget(app, appWidgetManager, id, noteId, noteType, locked = app.locked.value)
|
||||
updateWidget(app, appWidgetManager, id, noteId, noteType)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun updateWidgets(context: Context, noteIds: LongArray? = null, locked: Boolean) {
|
||||
fun updateWidgets(context: Context, noteIds: LongArray? = null, locked: Boolean = false) {
|
||||
val app = context.applicationContext as Application
|
||||
val preferences = NotallyXPreferences.getInstance(app)
|
||||
|
||||
|
@ -184,90 +181,65 @@ class WidgetProvider : AppWidgetProvider() {
|
|||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id)
|
||||
intent.embedIntentExtras()
|
||||
|
||||
MainScope().launch {
|
||||
if (!locked) {
|
||||
val database = NotallyDatabase.getDatabase(context).value
|
||||
val color =
|
||||
withContext(Dispatchers.IO) { database.getBaseNoteDao().getColorOfNote(noteId) }
|
||||
if (color == null) {
|
||||
val app = context.applicationContext as Application
|
||||
val preferences = NotallyXPreferences.getInstance(app)
|
||||
preferences.deleteWidget(id)
|
||||
val view =
|
||||
RemoteViews(context.packageName, R.layout.widget).apply {
|
||||
setRemoteAdapter(R.id.ListView, intent)
|
||||
setEmptyView(R.id.ListView, R.id.Empty)
|
||||
setOnClickPendingIntent(
|
||||
R.id.Empty,
|
||||
Intent(context, WidgetProvider::class.java)
|
||||
.apply {
|
||||
action = ACTION_SELECT_NOTE
|
||||
data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
|
||||
}
|
||||
.asPendingIntent(context),
|
||||
)
|
||||
setPendingIntentTemplate(
|
||||
R.id.ListView,
|
||||
Intent(context, WidgetProvider::class.java).asPendingIntent(context),
|
||||
)
|
||||
}
|
||||
|
||||
manager.updateAppWidget(id, view)
|
||||
manager.notifyAppWidgetViewDataChanged(id, R.id.ListView)
|
||||
return@launch
|
||||
}
|
||||
if (!locked) {
|
||||
val view =
|
||||
RemoteViews(context.packageName, R.layout.widget).apply {
|
||||
setRemoteAdapter(R.id.ListView, intent)
|
||||
setEmptyView(R.id.ListView, R.id.Empty)
|
||||
setOnClickPendingIntent(
|
||||
R.id.Empty,
|
||||
Intent(context, WidgetProvider::class.java)
|
||||
.apply {
|
||||
action = ACTION_SELECT_NOTE
|
||||
data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
|
||||
}
|
||||
.asPendingIntent(context),
|
||||
)
|
||||
setPendingIntentTemplate(
|
||||
R.id.ListView,
|
||||
Intent(context, WidgetProvider::class.java).asPendingIntent(context),
|
||||
)
|
||||
|
||||
val preferences = NotallyXPreferences.getInstance(context)
|
||||
val (backgroundColor, _) =
|
||||
context.extractWidgetColors(color, preferences)
|
||||
noteType?.let {
|
||||
MainScope().launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
val color = database.getBaseNoteDao().getColorOfNote(noteId)
|
||||
val preferences = NotallyXPreferences.getInstance(context)
|
||||
val (backgroundColor, _) = context.extractWidgetColors(color, preferences)
|
||||
val view =
|
||||
RemoteViews(context.packageName, R.layout.widget).apply {
|
||||
setRemoteAdapter(R.id.ListView, intent)
|
||||
setEmptyView(R.id.ListView, R.id.Empty)
|
||||
setOnClickPendingIntent(
|
||||
R.id.Layout,
|
||||
R.id.Empty,
|
||||
Intent(context, WidgetProvider::class.java)
|
||||
.setOpenNoteIntent(noteType, noteId)
|
||||
.apply {
|
||||
action = ACTION_SELECT_NOTE
|
||||
data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
|
||||
}
|
||||
.asPendingIntent(context),
|
||||
)
|
||||
setPendingIntentTemplate(
|
||||
R.id.ListView,
|
||||
Intent(context, WidgetProvider::class.java)
|
||||
.asPendingIntent(context),
|
||||
)
|
||||
|
||||
noteType?.let {
|
||||
setOnClickPendingIntent(
|
||||
R.id.Layout,
|
||||
Intent(context, WidgetProvider::class.java)
|
||||
.setOpenNoteIntent(noteType, noteId)
|
||||
.asPendingIntent(context),
|
||||
)
|
||||
}
|
||||
|
||||
setInt(R.id.Layout, "setBackgroundColor", backgroundColor)
|
||||
}
|
||||
setInt(R.id.Layout, "setBackgroundColor", backgroundColor)
|
||||
}
|
||||
manager.updateAppWidget(id, view)
|
||||
manager.notifyAppWidgetViewDataChanged(id, R.id.ListView)
|
||||
} else {
|
||||
val view =
|
||||
RemoteViews(context.packageName, R.layout.widget_locked).apply {
|
||||
noteType?.let {
|
||||
val lockedPendingIntent =
|
||||
context.getOpenNotePendingIntent(noteId, noteType)
|
||||
setOnClickPendingIntent(R.id.Layout, lockedPendingIntent)
|
||||
setOnClickPendingIntent(R.id.Text, lockedPendingIntent)
|
||||
}
|
||||
setTextViewCompoundDrawablesRelative(
|
||||
R.id.Text,
|
||||
0,
|
||||
R.drawable.lock_big,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
}
|
||||
manager.updateAppWidget(id, view)
|
||||
manager.updateAppWidget(id, view)
|
||||
manager.notifyAppWidgetViewDataChanged(id, R.id.ListView)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val view =
|
||||
RemoteViews(context.packageName, R.layout.widget_locked).apply {
|
||||
noteType?.let {
|
||||
val lockedPendingIntent =
|
||||
context.getOpenNotePendingIntent(noteId, noteType)
|
||||
setOnClickPendingIntent(R.id.Layout, lockedPendingIntent)
|
||||
setOnClickPendingIntent(R.id.Text, lockedPendingIntent)
|
||||
}
|
||||
setTextViewCompoundDrawablesRelative(
|
||||
R.id.Text,
|
||||
0,
|
||||
R.drawable.lock_big,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
}
|
||||
manager.updateAppWidget(id, view)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,13 +44,6 @@ class ActionMode {
|
|||
}
|
||||
}
|
||||
|
||||
fun updateSelected(availableItemIds: List<Long>?) {
|
||||
selectedNotes.keys
|
||||
.filter { availableItemIds?.contains(it) == false }
|
||||
.forEach { selectedNotes.remove(it) }
|
||||
refresh()
|
||||
}
|
||||
|
||||
fun isEnabled() = enabled.value
|
||||
|
||||
// We assume selectedNotes.size is 1
|
||||
|
|
|
@ -80,7 +80,7 @@ private fun Context.createReminderAlarmIntent(noteId: Long, reminderId: Long): P
|
|||
intent.putExtra(ReminderReceiver.EXTRA_NOTE_ID, noteId)
|
||||
return PendingIntent.getBroadcast(
|
||||
this,
|
||||
(noteId.toString() + reminderId.toString()).toInt(),
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE,
|
||||
)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.philkes.notallyx.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.KeyguardManager
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
|
@ -11,6 +12,7 @@ import android.content.ContentResolver
|
|||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
import android.hardware.biometrics.BiometricManager
|
||||
import android.net.Uri
|
||||
|
@ -45,6 +47,7 @@ import java.io.OutputStreamWriter
|
|||
import java.io.PrintWriter
|
||||
import java.lang.UnsupportedOperationException
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
@ -123,15 +126,30 @@ fun Context.getFileName(uri: Uri): String? =
|
|||
}
|
||||
|
||||
fun Context.canAuthenticateWithBiometrics(): Int {
|
||||
val biometricManager = androidx.biometric.BiometricManager.from(this)
|
||||
val authenticators =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG or
|
||||
androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
val keyguardManager = ContextCompat.getSystemService(this, KeyguardManager::class.java)
|
||||
val packageManager: PackageManager = this.packageManager
|
||||
if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
|
||||
return BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE
|
||||
}
|
||||
if (keyguardManager?.isKeyguardSecure == false) {
|
||||
return BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED
|
||||
}
|
||||
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||
val biometricManager: BiometricManager =
|
||||
this.getSystemService(BiometricManager::class.java)
|
||||
return biometricManager.canAuthenticate()
|
||||
} else {
|
||||
androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG
|
||||
val biometricManager: BiometricManager =
|
||||
this.getSystemService(BiometricManager::class.java)
|
||||
return biometricManager.canAuthenticate(
|
||||
BiometricManager.Authenticators.BIOMETRIC_STRONG or
|
||||
BiometricManager.Authenticators.DEVICE_CREDENTIAL
|
||||
)
|
||||
}
|
||||
return biometricManager.canAuthenticate(authenticators)
|
||||
}
|
||||
return BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE
|
||||
}
|
||||
|
||||
fun Context.getUriForFile(file: File): Uri =
|
||||
|
@ -155,7 +173,8 @@ fun ContextWrapper.log(
|
|||
fun ContextWrapper.getLastExceptionLog(): String? {
|
||||
val logFile = getLogFile()
|
||||
if (logFile.exists()) {
|
||||
return logFile.readText().substringAfterLast("[Start]")
|
||||
val logContents = logFile.readText().substringAfterLast("[Start]")
|
||||
return URLEncoder.encode(logContents, StandardCharsets.UTF_8.toString())
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
@ -185,10 +204,10 @@ fun Context.logToFile(
|
|||
val logFile =
|
||||
folder.findFile(fileName).let {
|
||||
if (it == null || !it.exists()) {
|
||||
folder.createFile("text/plain", fileName.removeSuffix(".txt"))
|
||||
folder.createFile("text/plain", fileName)
|
||||
} else if (it.isLargerThanKb(MAX_LOGS_FILE_SIZE_KB)) {
|
||||
it.delete()
|
||||
folder.createFile("text/plain", fileName.removeSuffix(".txt"))
|
||||
folder.createFile("text/plain", fileName)
|
||||
} else it
|
||||
}
|
||||
|
||||
|
@ -305,14 +324,14 @@ private fun Context.shareNote(title: String, body: CharSequence, imageUris: List
|
|||
val intent =
|
||||
Intent(if (imageUris.size > 1) Intent.ACTION_SEND_MULTIPLE else Intent.ACTION_SEND)
|
||||
.apply {
|
||||
type = if (imageUris.isEmpty()) "text/*" else "image/*"
|
||||
type = "image/*"
|
||||
putExtra(Intent.EXTRA_TEXT, text.toString())
|
||||
putExtra(Intent.EXTRA_TITLE, title)
|
||||
putExtra(Intent.EXTRA_SUBJECT, title)
|
||||
if (imageUris.size > 1) {
|
||||
putParcelableArrayListExtra(Intent.EXTRA_STREAM, ArrayList(imageUris))
|
||||
} else if (imageUris.isNotEmpty()) {
|
||||
putExtra(Intent.EXTRA_STREAM, imageUris.first())
|
||||
} else {
|
||||
putExtra(Intent.EXTRA_STREAM, imageUris.firstOrNull())
|
||||
}
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ fun Context.getExportedPath() = getEmptyFolder("exported")
|
|||
|
||||
fun ContextWrapper.getLogsDir() = File(filesDir, "logs").also { it.mkdir() }
|
||||
|
||||
const val APP_LOG_FILE_NAME = "notallyx-logs.txt"
|
||||
const val APP_LOG_FILE_NAME = "Log.v1.txt"
|
||||
|
||||
fun ContextWrapper.getLogFile(): File {
|
||||
return File(getLogsDir(), APP_LOG_FILE_NAME)
|
||||
|
|
|
@ -89,7 +89,7 @@ import net.lingala.zip4j.model.enums.EncryptionMethod
|
|||
private const val TAG = "ExportExtensions"
|
||||
private const val NOTIFICATION_CHANNEL_ID = "AutoBackups"
|
||||
private const val NOTIFICATION_ID = 123412
|
||||
private const val NOTALLYX_BACKUP_LOGS_FILE = "notallyx-backup-logs.txt"
|
||||
private const val NOTALLYX_BACKUP_LOGS_FILE = "notallyx-backup-logs"
|
||||
private const val OUTPUT_DATA_BACKUP_URI = "backupUri"
|
||||
|
||||
const val AUTO_BACKUP_WORK_NAME = "com.philkes.notallyx.AutoBackupWork"
|
||||
|
@ -174,7 +174,7 @@ fun ContextWrapper.autoBackupOnSave(backupPath: String, password: String, savedN
|
|||
backupFile = folder.createFile(MIME_TYPE_ZIP, ON_SAVE_BACKUP_FILE)
|
||||
exportAsZip(backupFile!!.uri, password = password)
|
||||
} else {
|
||||
val (_, file) = copyDatabase()
|
||||
NotallyDatabase.getDatabase(this, observePreferences = false).value.checkpoint()
|
||||
val files =
|
||||
with(savedNote) {
|
||||
images.map {
|
||||
|
@ -192,7 +192,10 @@ fun ContextWrapper.autoBackupOnSave(backupPath: String, password: String, savedN
|
|||
audios.map {
|
||||
BackupFile(SUBFOLDER_AUDIOS, File(getExternalAudioDirectory(), it.name))
|
||||
} +
|
||||
BackupFile(null, file)
|
||||
BackupFile(
|
||||
null,
|
||||
NotallyDatabase.getCurrentDatabaseFile(this@autoBackupOnSave),
|
||||
)
|
||||
}
|
||||
try {
|
||||
exportToZip(backupFile.uri, files, password)
|
||||
|
@ -414,7 +417,7 @@ fun ContextWrapper.copyDatabase(): Pair<NotallyDatabase, File> {
|
|||
val cipher = getInitializedCipherForDecryption(iv = preferences.iv.value!!)
|
||||
val passphrase = cipher.doFinal(preferences.databaseEncryptionKey.value)
|
||||
val decryptedFile = File(cacheDir, DATABASE_NAME)
|
||||
decryptDatabase(this, passphrase, databaseFile, decryptedFile)
|
||||
decryptDatabase(this, passphrase, decryptedFile, databaseFile)
|
||||
Pair(database, decryptedFile)
|
||||
} else {
|
||||
val dbFile = File(cacheDir, DATABASE_NAME)
|
||||
|
@ -514,14 +517,13 @@ fun exportPdfFile(
|
|||
total: Int? = null,
|
||||
duplicateFileCount: Int = 1,
|
||||
) {
|
||||
val validFileName = fileName.ifBlank { app.getString(R.string.note) }
|
||||
val filePath = "$validFileName.${ExportMimeType.PDF.fileExtension}"
|
||||
val filePath = "$fileName.${ExportMimeType.PDF.fileExtension}"
|
||||
if (folder.findFile(filePath)?.exists() == true) {
|
||||
return exportPdfFile(
|
||||
app,
|
||||
note,
|
||||
folder,
|
||||
"${validFileName.removeTrailingParentheses()} ($duplicateFileCount)",
|
||||
"${fileName.removeTrailingParentheses()} ($duplicateFileCount)",
|
||||
pdfPrintListener,
|
||||
progress,
|
||||
counter,
|
||||
|
|
|
@ -28,7 +28,6 @@ import com.philkes.notallyx.data.model.parseToColorString
|
|||
import com.philkes.notallyx.presentation.getQuantityString
|
||||
import com.philkes.notallyx.presentation.showToast
|
||||
import com.philkes.notallyx.presentation.viewmodel.NotallyModel.FileType
|
||||
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
|
||||
import com.philkes.notallyx.utils.FileError
|
||||
import com.philkes.notallyx.utils.SUBFOLDER_AUDIOS
|
||||
import com.philkes.notallyx.utils.SUBFOLDER_FILES
|
||||
|
@ -45,8 +44,6 @@ import com.philkes.notallyx.utils.log
|
|||
import com.philkes.notallyx.utils.mimeTypeToFileExtension
|
||||
import com.philkes.notallyx.utils.rename
|
||||
import com.philkes.notallyx.utils.scheduleNoteReminders
|
||||
import com.philkes.notallyx.utils.security.SQLCipherUtils
|
||||
import com.philkes.notallyx.utils.security.decryptDatabase
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStream
|
||||
|
@ -89,31 +86,12 @@ suspend fun ContextWrapper.importZip(
|
|||
NotallyDatabase.DATABASE_NAME,
|
||||
)
|
||||
|
||||
var dbFile = File(databaseFolder, NotallyDatabase.DATABASE_NAME)
|
||||
val state = SQLCipherUtils.getDatabaseState(dbFile)
|
||||
if (state == SQLCipherUtils.State.ENCRYPTED) {
|
||||
val fallbackEncryptionKey =
|
||||
NotallyXPreferences.getInstance(this@importZip)
|
||||
.fallbackDatabaseEncryptionKey
|
||||
.value
|
||||
if (fallbackEncryptionKey != null) {
|
||||
val dbFileDecrypted =
|
||||
File(databaseFolder, "${NotallyDatabase.DATABASE_NAME}-decrypted")
|
||||
decryptDatabase(
|
||||
this@importZip,
|
||||
fallbackEncryptionKey,
|
||||
dbFile,
|
||||
dbFileDecrypted,
|
||||
)
|
||||
dbFile = dbFileDecrypted
|
||||
} else {
|
||||
throw IllegalArgumentException(
|
||||
"Backup contains encrypted database and 'fallbackDatabaseEncryptionKey' has no value!"
|
||||
)
|
||||
}
|
||||
}
|
||||
val database =
|
||||
SQLiteDatabase.openDatabase(dbFile.path, null, SQLiteDatabase.OPEN_READONLY)
|
||||
SQLiteDatabase.openDatabase(
|
||||
File(databaseFolder, NotallyDatabase.DATABASE_NAME).path,
|
||||
null,
|
||||
SQLiteDatabase.OPEN_READONLY,
|
||||
)
|
||||
|
||||
val labelCursor = database.query("Label", null, null, null, null, null, null)
|
||||
val baseNoteCursor = database.query("BaseNote", null, null, null, null, null, null)
|
||||
|
@ -199,11 +177,14 @@ suspend fun ContextWrapper.importZip(
|
|||
showToast(message)
|
||||
} catch (e: ZipException) {
|
||||
if (e.type == ZipException.Type.WRONG_PASSWORD) {
|
||||
log(TAG, throwable = e)
|
||||
showToast(R.string.wrong_password)
|
||||
} else {
|
||||
throw e
|
||||
log(TAG, throwable = e)
|
||||
showToast(R.string.invalid_backup)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
showToast(R.string.invalid_backup)
|
||||
log(TAG, throwable = e)
|
||||
} finally {
|
||||
importingBackup?.value = ImportProgress(inProgress = false)
|
||||
}
|
||||
|
|
|
@ -37,8 +37,8 @@ fun decryptDatabase(context: ContextWrapper, passphrase: ByteArray) {
|
|||
fun decryptDatabase(
|
||||
context: Context,
|
||||
passphrase: ByteArray,
|
||||
databaseFile: File,
|
||||
decryptedFile: File,
|
||||
databaseFile: File,
|
||||
) {
|
||||
val state = SQLCipherUtils.getDatabaseState(databaseFile)
|
||||
if (state == SQLCipherUtils.State.ENCRYPTED) {
|
||||
|
|
|
@ -4,13 +4,15 @@ import android.app.Activity
|
|||
import android.app.KeyguardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.hardware.biometrics.BiometricManager
|
||||
import android.hardware.biometrics.BiometricPrompt
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.os.Build
|
||||
import android.os.CancellationSignal
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.biometric.BiometricManager
|
||||
import androidx.biometric.BiometricPrompt
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.philkes.notallyx.R
|
||||
import javax.crypto.Cipher
|
||||
|
||||
|
@ -25,7 +27,7 @@ fun Activity.showBiometricOrPinPrompt(
|
|||
) {
|
||||
showBiometricOrPinPrompt(
|
||||
isForDecrypt,
|
||||
this as FragmentActivity,
|
||||
this,
|
||||
activityResultLauncher,
|
||||
titleResId,
|
||||
descriptionResId,
|
||||
|
@ -46,7 +48,7 @@ fun Fragment.showBiometricOrPinPrompt(
|
|||
) {
|
||||
showBiometricOrPinPrompt(
|
||||
isForDecrypt,
|
||||
activity!!,
|
||||
requireContext(),
|
||||
activityResultLauncher,
|
||||
titleResId,
|
||||
descriptionResId,
|
||||
|
@ -58,7 +60,7 @@ fun Fragment.showBiometricOrPinPrompt(
|
|||
|
||||
private fun showBiometricOrPinPrompt(
|
||||
isForDecrypt: Boolean,
|
||||
context: FragmentActivity,
|
||||
context: Context,
|
||||
activityResultLauncher: ActivityResultLauncher<Intent>,
|
||||
titleResId: Int,
|
||||
descriptionResId: Int? = null,
|
||||
|
@ -67,24 +69,65 @@ private fun showBiometricOrPinPrompt(
|
|||
onFailure: (errorCode: Int?) -> Unit,
|
||||
) {
|
||||
when {
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
|
||||
val promptInfo =
|
||||
BiometricPrompt.PromptInfo.Builder()
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> {
|
||||
// Android 11+ with BiometricPrompt and Authenticators
|
||||
val prompt =
|
||||
BiometricPrompt.Builder(context)
|
||||
.apply {
|
||||
setTitle(context.getString(titleResId))
|
||||
descriptionResId?.let {
|
||||
setDescription(context.getString(descriptionResId))
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
setAllowedAuthenticators(
|
||||
BiometricManager.Authenticators.BIOMETRIC_STRONG or
|
||||
BiometricManager.Authenticators.DEVICE_CREDENTIAL
|
||||
)
|
||||
} else {
|
||||
setNegativeButtonText(context.getString(R.string.cancel))
|
||||
setAllowedAuthenticators(
|
||||
BiometricManager.Authenticators.BIOMETRIC_STRONG
|
||||
)
|
||||
setAllowedAuthenticators(
|
||||
BiometricManager.Authenticators.BIOMETRIC_STRONG or
|
||||
BiometricManager.Authenticators.DEVICE_CREDENTIAL
|
||||
)
|
||||
}
|
||||
.build()
|
||||
val cipher =
|
||||
if (isForDecrypt) {
|
||||
getInitializedCipherForDecryption(iv = cipherIv!!)
|
||||
} else {
|
||||
getInitializedCipherForEncryption()
|
||||
}
|
||||
prompt.authenticate(
|
||||
BiometricPrompt.CryptoObject(cipher),
|
||||
getCancellationSignal(context),
|
||||
context.mainExecutor,
|
||||
object : BiometricPrompt.AuthenticationCallback() {
|
||||
override fun onAuthenticationSucceeded(
|
||||
result: BiometricPrompt.AuthenticationResult?
|
||||
) {
|
||||
super.onAuthenticationSucceeded(result)
|
||||
onSuccess.invoke(result!!.cryptoObject!!.cipher)
|
||||
}
|
||||
|
||||
override fun onAuthenticationFailed() {
|
||||
super.onAuthenticationFailed()
|
||||
onFailure.invoke(null)
|
||||
}
|
||||
|
||||
override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) {
|
||||
super.onAuthenticationError(errorCode, errString)
|
||||
onFailure.invoke(errorCode)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
Build.VERSION.SDK_INT == Build.VERSION_CODES.Q -> {
|
||||
// Android 10: Use BiometricPrompt without Authenticators
|
||||
val prompt =
|
||||
BiometricPrompt.Builder(context)
|
||||
.apply {
|
||||
setTitle(context.getString(titleResId))
|
||||
descriptionResId?.let {
|
||||
setDescription(context.getString(descriptionResId))
|
||||
}
|
||||
setNegativeButton(
|
||||
context.getString(R.string.cancel),
|
||||
context.mainExecutor,
|
||||
) { _, _ ->
|
||||
onFailure.invoke(null)
|
||||
}
|
||||
}
|
||||
.build()
|
||||
|
@ -94,13 +137,16 @@ private fun showBiometricOrPinPrompt(
|
|||
} else {
|
||||
getInitializedCipherForEncryption()
|
||||
}
|
||||
val authCallback =
|
||||
prompt.authenticate(
|
||||
BiometricPrompt.CryptoObject(cipher),
|
||||
getCancellationSignal(context),
|
||||
context.mainExecutor,
|
||||
object : BiometricPrompt.AuthenticationCallback() {
|
||||
override fun onAuthenticationSucceeded(
|
||||
result: BiometricPrompt.AuthenticationResult
|
||||
result: BiometricPrompt.AuthenticationResult?
|
||||
) {
|
||||
super.onAuthenticationSucceeded(result)
|
||||
onSuccess.invoke(result.cryptoObject!!.cipher!!)
|
||||
onSuccess.invoke(result!!.cryptoObject!!.cipher)
|
||||
}
|
||||
|
||||
override fun onAuthenticationFailed() {
|
||||
|
@ -108,14 +154,57 @@ private fun showBiometricOrPinPrompt(
|
|||
onFailure.invoke(null)
|
||||
}
|
||||
|
||||
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
||||
override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) {
|
||||
super.onAuthenticationError(errorCode, errString)
|
||||
onFailure.invoke(errorCode)
|
||||
}
|
||||
}
|
||||
val prompt =
|
||||
BiometricPrompt(context, ContextCompat.getMainExecutor(context), authCallback)
|
||||
prompt.authenticate(promptInfo, BiometricPrompt.CryptoObject(cipher))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
|
||||
val fingerprintManager =
|
||||
ContextCompat.getSystemService(context, FingerprintManager::class.java)
|
||||
if (
|
||||
fingerprintManager?.isHardwareDetected == true &&
|
||||
fingerprintManager.hasEnrolledFingerprints()
|
||||
) {
|
||||
val cipher =
|
||||
if (isForDecrypt) {
|
||||
getInitializedCipherForDecryption(iv = cipherIv!!)
|
||||
} else {
|
||||
getInitializedCipherForEncryption()
|
||||
}
|
||||
fingerprintManager.authenticate(
|
||||
FingerprintManager.CryptoObject(cipher),
|
||||
getCancellationSignal(context),
|
||||
0,
|
||||
object : FingerprintManager.AuthenticationCallback() {
|
||||
override fun onAuthenticationSucceeded(
|
||||
result: FingerprintManager.AuthenticationResult?
|
||||
) {
|
||||
super.onAuthenticationSucceeded(result)
|
||||
onSuccess.invoke(result!!.cryptoObject!!.cipher)
|
||||
}
|
||||
|
||||
override fun onAuthenticationFailed() {
|
||||
super.onAuthenticationFailed()
|
||||
onFailure.invoke(null)
|
||||
}
|
||||
|
||||
override fun onAuthenticationError(
|
||||
errorCode: Int,
|
||||
errString: CharSequence?,
|
||||
) {
|
||||
super.onAuthenticationError(errorCode, errString)
|
||||
onFailure.invoke(errorCode)
|
||||
}
|
||||
},
|
||||
null,
|
||||
)
|
||||
} else {
|
||||
promptPinAuthentication(context, activityResultLauncher, titleResId, onFailure)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
|
@ -125,6 +214,14 @@ private fun showBiometricOrPinPrompt(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getCancellationSignal(context: Context): CancellationSignal {
|
||||
return CancellationSignal().apply {
|
||||
setOnCancelListener {
|
||||
Toast.makeText(context, R.string.biometrics_failure, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun promptPinAuthentication(
|
||||
context: Context,
|
||||
activityResultLauncher: ActivityResultLauncher<Intent>,
|
||||
|
|
|
@ -8,5 +8,6 @@
|
|||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/EditText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textCapWords" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
|
@ -1,55 +1,47 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/RepetitionOptions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:padding="16dp">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/None"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scrollbarAlwaysDrawVerticalTrack="true">
|
||||
android:checked="true"
|
||||
android:text="@string/none" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/RepetitionOptions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp">
|
||||
<RadioButton
|
||||
android:id="@+id/Daily"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/daily" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/None"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:text="@string/none" />
|
||||
<RadioButton
|
||||
android:id="@+id/Weekly"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/weekly" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/Daily"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/daily" />
|
||||
<RadioButton
|
||||
android:id="@+id/Monthly"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/monthly" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/Weekly"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/weekly" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/Monthly"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/monthly" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/Yearly"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/yearly" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/Custom"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/custom" />
|
||||
</RadioGroup>
|
||||
</ScrollView>
|
||||
<RadioButton
|
||||
android:id="@+id/Yearly"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/yearly" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/Custom"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/custom" />
|
||||
</RadioGroup>
|
||||
|
||||
|
|
|
@ -88,10 +88,6 @@
|
|||
android:id="@+id/LabelsHiddenInOverview"
|
||||
layout="@layout/preference" />
|
||||
|
||||
<include
|
||||
android:id="@+id/ImagesHiddenInOverview"
|
||||
layout="@layout/preference" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
|
@ -177,10 +173,6 @@
|
|||
android:id="@+id/BackupPassword"
|
||||
layout="@layout/preference" />
|
||||
|
||||
<include
|
||||
android:id="@+id/SecureFlag"
|
||||
layout="@layout/preference" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
<string name="auto_backup_last">Poslední záloha</string>
|
||||
<string name="auto_backup_on_save">Automaticky zálohovat při ukončení poznámky</string>
|
||||
<string name="auto_backup_on_save_hint">Pokud tuto možnost povolíte, záloha („NotallyX_AutoBackup.zip“) bude automaticky vytvořena ve zvoleném „Adresáři záloh“ pokaždé, když bude poznámka uložena. Mějte na paměti, že to může ovlivnit výkon</string>
|
||||
<string name="auto_backup_period">Frekvence automatického zálohování</string>
|
||||
<string name="auto_backups_folder">Adresář pro zálohy</string>
|
||||
<string name="auto_backups_folder_hint">Adresář pro uložení automatických záloh.</string>
|
||||
<string name="auto_backups_folder_rechoose">Vyberte znovu Adresář pro zálohy a udělte tak znovu NotallyX oprávnění do něj zapisovat.\nPro přeskočení můžete stisknout tlačítko Zrušit</string>
|
||||
|
@ -96,6 +97,7 @@
|
|||
<string name="date_format_apply_in_note_view">Použít také v poznámkách</string>
|
||||
<string name="date_format_hint">Nastaví vybraný formát data v přehledu poznámek</string>
|
||||
<string name="days">Dny</string>
|
||||
<string name="default_note_view_mode">Výchozí zobrazení poznámky</string>
|
||||
<string name="delete">Smazat</string>
|
||||
<string name="delete_all">Smazat vše</string>
|
||||
<string name="delete_all_notes">Smazat všechny poznámky\?</string>
|
||||
|
@ -123,7 +125,6 @@
|
|||
<string name="disable_lock_description">Toto rovněž dešifruje databázi</string>
|
||||
<string name="disable_lock_title">Vypnout zámek pomocí biometrických údajů/PIN</string>
|
||||
<string name="disabled">Zakázat</string>
|
||||
<string name="disallow_screenshots">Zakázat pořizování snímků obrazovky</string>
|
||||
<string name="discard">Zahodit</string>
|
||||
<string name="display_text">Text k zobrazení</string>
|
||||
<string name="donate">Podpořit</string>
|
||||
|
@ -163,8 +164,6 @@
|
|||
<string name="help">Nápověda</string>
|
||||
<string name="hours">Hodiny</string>
|
||||
<string name="image_format_not_supported">Formát obrázku není podporován</string>
|
||||
<string name="images_hidden_in_overview">Pokud tuto funkci povolíte, obrázky poznámek budou v přehledu skryty.</string>
|
||||
<string name="images_hidden_in_overview_title">Skrýt obrázky v přehledu</string>
|
||||
<string name="import_action">Importovat</string>
|
||||
<string name="import_backup">Importovat zálohu</string>
|
||||
<string name="import_backup_password_hint">Pokud vaše záloha není chráněna heslem, jednoduše stiskněte tlačítko Importovat, jinak zadejte správné heslo.</string>
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
<string name="auto_backup_last">Letztes Backup</string>
|
||||
<string name="auto_backup_on_save">Autom. Backup beim Notiz Verlassen</string>
|
||||
<string name="auto_backup_on_save_hint">Ist dies aktiviert, wird jedesmal wenn eine Notiz verlassen wird autom. ein Backup (\"NotallyX_AutoBackup.zip\") im \"Backups Ordner\" erstellt.\nDies kann die App-Performance beeinträchtigen</string>
|
||||
<string name="auto_backup_period">Intervall für autom. Backups</string>
|
||||
<string name="auto_backups_folder">Backups Ordner</string>
|
||||
<string name="auto_backups_folder_hint">Ordner in dem alle autom. Backups erstellt werden</string>
|
||||
<string name="auto_backups_folder_rechoose">Der Backups Ordner muss erneut ausgewählt werden, damit NotallyX Schreibrechte dafür erhält.\nÜber Abbrechen kann der Import dieser Einstellung übersprungen werden.</string>
|
||||
|
@ -119,7 +120,6 @@
|
|||
<string name="disable_lock_description">Dies entschlüsselt außerdem die Datenbank</string>
|
||||
<string name="disable_lock_title">Deaktivierte Biometrie/PIN Sperre</string>
|
||||
<string name="disabled">Deaktiviert</string>
|
||||
<string name="disallow_screenshots">Screenshots verbieten</string>
|
||||
<string name="discard">Verwerfen</string>
|
||||
<string name="display_text">Anzeigetext</string>
|
||||
<string name="donate">Spende</string>
|
||||
|
@ -159,8 +159,6 @@
|
|||
<string name="help">Hilfe</string>
|
||||
<string name="hours">Stunden</string>
|
||||
<string name="image_format_not_supported">Bildformat nicht unterstützt</string>
|
||||
<string name="images_hidden_in_overview">Ist dies aktiviert, werden die Bilder der Notizen in der Übersicht ausgeblendet</string>
|
||||
<string name="images_hidden_in_overview_title">Verberge Bilder in Übersicht</string>
|
||||
<string name="import_action">Import</string>
|
||||
<string name="import_backup">Backup importieren</string>
|
||||
<string name="import_backup_password_hint">Falls das Backup nicht passwortgeschützt ist, drücken Sie einfach auf Importieren, andernfalls geben Sie das richtige Passwort ein.</string>
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
<string name="auto_backup_last">Última copia de seguridad</string>
|
||||
<string name="auto_backup_on_save">Copia de seguridad automática al salir una nota</string>
|
||||
<string name="auto_backup_on_save_hint">Al habilitar esta opción, se crea automáticamente una copia de seguridad (\"NotallyX_AutoBackup.zip\") en la \"Directorio de copias de seguridad\" configurada cada vez que se guarda una nota.\nTenga en cuenta que esto puede afectar el rendimiento.</string>
|
||||
<string name="auto_backup_period">Periodo de copia automática</string>
|
||||
<string name="auto_backups_folder">Directorio de copias de seguridad</string>
|
||||
<string name="auto_backups_folder_hint">Carpeta donde se guardan las copias de seguridad automáticas.</string>
|
||||
<string name="auto_backups_folder_rechoose">Debe volver a elegir su directorio de copias de seguridad para que NotallyX tenga permiso para escribir en ella.\nTambién puede presionar Cancelar para omitir la importación del valor del directorio de copias de seguridad</string>
|
||||
|
@ -93,6 +94,7 @@
|
|||
<string name="date_format_apply_in_note_view">Aplicar también en la vista de nota</string>
|
||||
<string name="date_format_hint">Aplica el formato de fecha seleccionado en la vista general de notas</string>
|
||||
<string name="days">Días</string>
|
||||
<string name="default_note_view_mode">Modo de vista de nota por omisión</string>
|
||||
<string name="delete">Eliminar</string>
|
||||
<string name="delete_all">Borrar todo</string>
|
||||
<string name="delete_all_notes">¿Borrar todas las notas\?</string>
|
||||
|
@ -119,7 +121,6 @@
|
|||
<string name="disable_lock_description">Esto también descifrará la base de datos</string>
|
||||
<string name="disable_lock_title">Deshabilitar bloqueo biométrico/PIN</string>
|
||||
<string name="disabled">Deshabilitado</string>
|
||||
<string name="disallow_screenshots">No permitir capturas de pantalla</string>
|
||||
<string name="discard">Descartar</string>
|
||||
<string name="display_text">Texto a pantalla</string>
|
||||
<string name="donate">Hacer donación</string>
|
||||
|
@ -159,8 +160,6 @@
|
|||
<string name="help">Ayuda</string>
|
||||
<string name="hours">Horas</string>
|
||||
<string name="image_format_not_supported">Formato de imagen no soportado</string>
|
||||
<string name="images_hidden_in_overview">Al habilitar esta opción, se ocultarán las imágenes de notas de la descripción general.</string>
|
||||
<string name="images_hidden_in_overview_title">Ocultar imágenes en vista general</string>
|
||||
<string name="import_action">Importar</string>
|
||||
<string name="import_backup">Importar copia de seguridad</string>
|
||||
<string name="import_backup_password_hint">Si su copia de seguridad no está protegida con contraseña, simplemente presione Importar, de lo contrario ingrese la contraseña correcta.</string>
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
<string name="auto_backups_folder_hint">Dossier dans lequel toutes les sauvegardes automatiques seront stockées.</string>
|
||||
<string name="auto_backups_folder_rechoose">Vous devez re-sélectionner votre dossier de sauvegarde afin que NotallyX ait l\'autorisation d\'y écrire.\nVous pouvez également appuyer sur Annuler pour ignorer l\'importation du chemin du dossier de sauvegarde.</string>
|
||||
<string name="auto_backups_folder_set">Configurer d\'abord le Dossier des sauvegardes</string>
|
||||
<string name="auto_save_after_idle_time">Enregistrer la note après un temps d’inactivité défini</string>
|
||||
<string name="auto_sort_by_checked">Trier les éléments cochés à la fin</string>
|
||||
<string name="back">Retour</string>
|
||||
<string name="backup">Sauvegarde</string>
|
||||
|
@ -37,7 +36,6 @@
|
|||
<string name="backup_period_days">Fréquence de sauvegarde périodique en jours</string>
|
||||
<string name="backup_periodic">Sauvegardes périodiques</string>
|
||||
<string name="backup_periodic_hint">En activant cette option, des sauvegardes sont automatiquement créées dans le Dossier de sauvegardes configuré.\nCela peut ne pas fonctionner si le mode économie d\'énergie est activé. </string>
|
||||
<string name="behaviour">Comportement</string>
|
||||
<string name="biometric_lock">Verrouiller l\'application avec la biométrie ou le code PIN de l\'appareil</string>
|
||||
<string name="biometrics_disable_success">Le verrouillage biométrique/code PIN a été désactivé</string>
|
||||
<string name="biometrics_failure">Échec de l\'authentification biométrique/code PIN</string>
|
||||
|
@ -119,7 +117,6 @@
|
|||
<string name="disable_lock_description">La base de donnée sera aussi décryptée</string>
|
||||
<string name="disable_lock_title">Désactiver le verrouillage biométrique/code PIN</string>
|
||||
<string name="disabled">Désactivé</string>
|
||||
<string name="disallow_screenshots">Bloquer les captures d’écran</string>
|
||||
<string name="discard">Supprimer</string>
|
||||
<string name="display_text">Texte à afficher</string>
|
||||
<string name="donate">Faire un don</string>
|
||||
|
@ -159,8 +156,6 @@
|
|||
<string name="help">Aide</string>
|
||||
<string name="hours">Heures</string>
|
||||
<string name="image_format_not_supported">Format d\'image non supporté</string>
|
||||
<string name="images_hidden_in_overview">En activant cette option, les images des notes seront masquées dans l\'aperçu</string>
|
||||
<string name="images_hidden_in_overview_title">Masquer les images dans la vue d\'ensemble</string>
|
||||
<string name="import_action">Importer</string>
|
||||
<string name="import_backup">Importer une sauvegarde</string>
|
||||
<string name="import_backup_password_hint">Si votre sauvegarde n\'est pas protégée par mot de passe, cliquez seulement sur \"Importer une sauvegarde\", sinon entrez le mot de passe correspondant.</string>
|
||||
|
@ -188,8 +183,6 @@
|
|||
<string name="invalid_link">Copier un lien valide dans le presse-papier</string>
|
||||
<string name="italic">Italique</string>
|
||||
<string name="item">Élément</string>
|
||||
<string name="json_files">Fichiers JSON</string>
|
||||
<string name="json_files_help">Pour importer vos notes depuis des fichiers JSON (fichier unique ou dossier), cliquez sur Importer. Chaque fichier JSON valide sera importé en tant que note individuelle et son nom de fichier deviendra le titre de la note.</string>
|
||||
<string name="label_exists">L\'étiquette existe déjà</string>
|
||||
<string name="label_visibility">Masquer/Afficher l\'étiquette dans le panneau de navigation</string>
|
||||
<string name="labels">Étiquettes</string>
|
||||
|
@ -244,7 +237,6 @@
|
|||
<string name="please_grant_notally_notification_auto_backup">Si une sauvegarde automatique échoue, vous pouvez recevoir une notification en accordant à NotallyX l\'autorisation d\'envoyer des notifications</string>
|
||||
<string name="previous">Précédent</string>
|
||||
<string name="rate">Noter cette application</string>
|
||||
<string name="read_only">Lecture seule</string>
|
||||
<string name="ready_to_record">Prêt à enregistrer</string>
|
||||
<string name="record_audio">Enregistrer un audio</string>
|
||||
<string name="recording">Enregistrement en cours…</string>
|
||||
|
@ -299,7 +291,6 @@
|
|||
<string name="text_default">Défaut</string>
|
||||
<string name="text_size">Taille du texte</string>
|
||||
<string name="theme">Thème</string>
|
||||
<string name="theme_use_dynamic_colors">Utiliser les couleurs de fond d’écran du système</string>
|
||||
<string name="title">Titre</string>
|
||||
<string name="to_record_audio">Pour enregistrer de l\'audio, autorisez NotallyX à accéder à votre microphone. Cliquez sur Paramètres > Autorisations et activez le microphone.</string>
|
||||
<string name="unarchive">Restaurer</string>
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
<string name="auto_backup_last">Ultimo backup</string>
|
||||
<string name="auto_backup_on_save">Backup automatico dopo l\'uscita dalla nota</string>
|
||||
<string name="auto_backup_on_save_hint">Abilitando questa opzione, un backup (NotallyX_AutoBackup.zip) verrà creato automaticamente nella \"Cartella di Backup\" configurata ogni volta che una nota viene salvata.\nTieni presente che questa operazione potrebbe influire sulle prestazioni</string>
|
||||
<string name="auto_backup_period">Frequenza dei backup automatici</string>
|
||||
<string name="auto_backups_folder">Cartella backup</string>
|
||||
<string name="auto_backups_folder_hint">Cartella in cui tutti i backup automatici verranno salvati.</string>
|
||||
<string name="auto_backups_folder_rechoose">Devi selezionare nuovamente la tua cartella di backup affinché NotallyX abbia l\'autorizzazione per scriverci.\nPuoi anche premere annulla per saltare l\'importazione del valore della cartella di backup.</string>
|
||||
|
@ -153,8 +154,6 @@
|
|||
<string name="help">Aiuto</string>
|
||||
<string name="hours">Ore</string>
|
||||
<string name="image_format_not_supported">Formato immagine non supportato</string>
|
||||
<string name="images_hidden_in_overview">Abilitando questa opzione le immagini delle note verranno nascoste nella panoramica.</string>
|
||||
<string name="images_hidden_in_overview_title">Nascondi immagini nella panoramica</string>
|
||||
<string name="import_action">Importa</string>
|
||||
<string name="import_backup">Importa backup</string>
|
||||
<string name="import_backup_password_hint">Se il tuo backup non è protetto da password premi semplicemente Importa, altrimenti inserisci la password corretta.</string>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<string name="attach_file">Bestand bijvoegen</string>
|
||||
<string name="audio_recordings">Audio-opnames</string>
|
||||
<string name="auto_backup">Automatische back-up</string>
|
||||
<string name="auto_backup_period">Periode van automatische back-up</string>
|
||||
<string name="auto_sort_by_checked">Sorteer de aangevinkte items tot het einde</string>
|
||||
<string name="backup">Back-up</string>
|
||||
<string name="backup_password">Backup Wachtwoord</string>
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
<string name="archive">Zarchwizuj</string>
|
||||
<string name="archived">Zarchiwizowane</string>
|
||||
<plurals name="archived_selected_notes">
|
||||
<item quantity="few">Zarchiwizowano %1$d notatki</item>
|
||||
<item quantity="many">Zarchiwizowano %1$d notatek</item>
|
||||
<item quantity="one">Zarchiwizowano %1$d notatkę</item>
|
||||
<item quantity="other">Zarchiwizowano %1$d notatek</item>
|
||||
</plurals>
|
||||
|
@ -26,11 +24,11 @@
|
|||
<string name="auto_backup_last">Ostatnia kopia zapasowa</string>
|
||||
<string name="auto_backup_on_save">Kopia zapasowa po wyjściu z notatki</string>
|
||||
<string name="auto_backup_on_save_hint">Po włączeniu tej opcji kopia zapasowa („NotallyX_AutoBackup.zip”) jest automatycznie tworzona w skonfigurowanym „Folderze kopii zapasowych” za każdym razem, gdy zapisywana jest notatka.\nPamiętaj, że może mieć to wpływ na wydajność</string>
|
||||
<string name="auto_backup_period">Okres tworzenia automatycznych kopii zapasowych</string>
|
||||
<string name="auto_backups_folder">Folder kopii zapasowych</string>
|
||||
<string name="auto_backups_folder_hint">Folder, w którym będą przechowywane wszystkie automatyczne kopie zapasowe.</string>
|
||||
<string name="auto_backups_folder_rechoose">Musisz ponownie wybrać folder kopii zapasowych, aby NotallyX miał uprawnienia do zapisu w nim.\nMożesz także nacisnąć Anuluj, aby pominąć importowanie zawartości folderu kopii zapasowych</string>
|
||||
<string name="auto_backups_folder_set">Najpierw skonfiguruj folder kopii zapasowych powyżej</string>
|
||||
<string name="auto_save_after_idle_time">Automatycznie zapisz notatkę po określonym czasie bezczynności</string>
|
||||
<string name="auto_sort_by_checked">Przenieś zaznaczone elementy na koniec</string>
|
||||
<string name="back">Cofnij</string>
|
||||
<string name="backup">Kopia zapasowa</string>
|
||||
|
@ -39,7 +37,6 @@
|
|||
<string name="backup_period_days">Częstotliwość tworzenia automatycznych kopii zapasowych w dniach</string>
|
||||
<string name="backup_periodic">Powtarzalne kopie zapasowe</string>
|
||||
<string name="backup_periodic_hint">Po włączeniu tej opcji kopie zapasowe są automatycznie tworzone w skonfigurowanym folderze kopii zapasowych.\nMoże to nie działać, jeśli włączony jest tryb oszczędzania energii</string>
|
||||
<string name="behaviour">Zachowanie</string>
|
||||
<string name="biometric_lock">Zablokuj aplikację za pomocą danych biometrycznych lub PIN-u urządzenia</string>
|
||||
<string name="biometrics_disable_success">Blokada biometryczna/PIN została wyłączona</string>
|
||||
<string name="biometrics_failure">Nie udało się uwierzytelnić za pomocą biometrii/PIN-u</string>
|
||||
|
@ -50,8 +47,6 @@
|
|||
<string name="calculating">Obliczanie…</string>
|
||||
<string name="cancel">Anuluj</string>
|
||||
<plurals name="cant_add_files">
|
||||
<item quantity="few">Nie można dodać %1$d plików</item>
|
||||
<item quantity="many">Nie można dodać %1$d plików</item>
|
||||
<item quantity="one">Nie można dodać %1$d pliku</item>
|
||||
<item quantity="other">Nie można dodać %1$d plików</item>
|
||||
</plurals>
|
||||
|
@ -78,12 +73,9 @@
|
|||
<string name="clear_data_message">Wszystkie notatki, obrazy, pliki i nagrania zostaną bezpowrotnie usunięte</string>
|
||||
<string name="clear_formatting">Usuń formatowanie</string>
|
||||
<string name="cleared_data">Wszystkie dane zostały usunięte</string>
|
||||
<string name="color">Kolor</string>
|
||||
<string name="color_exists">Ten kolor już istnieje!</string>
|
||||
<string name="content_density">Zagęszczenie treści</string>
|
||||
<string name="continue_">Kontynuuj</string>
|
||||
<string name="convert_to_list_note">Zamień na listę</string>
|
||||
<string name="convert_to_text_note">Zamień na notatkę</string>
|
||||
<string name="copied_link">Skopiowano link do schowka</string>
|
||||
<string name="copy">Skopiuj</string>
|
||||
<string name="crash_message">Wystąpił nieoczekiwany błąd.\nPrzepraszam za niedogodności.</string>
|
||||
|
@ -114,8 +106,6 @@
|
|||
<string name="delete_selected_notes">Usunąć zaznaczone notatki\?</string>
|
||||
<string name="deleted">Usunięte</string>
|
||||
<plurals name="deleted_selected_notes">
|
||||
<item quantity="few">Usunięto %1$d notatki</item>
|
||||
<item quantity="many">Usunięto %1$d notatek</item>
|
||||
<item quantity="one">Usunięto %1$d notatkę</item>
|
||||
<item quantity="other">Usunięto %1$d notatek</item>
|
||||
</plurals>
|
||||
|
@ -147,7 +137,7 @@
|
|||
<string name="error_while_renaming_file">Błąd podczas zmiany nazwy pliku</string>
|
||||
<string name="error_while_renaming_image">Błąd podczas zmiany nazwy obrazu</string>
|
||||
<string name="evernote">Evernote</string>
|
||||
<string name="evernote_help">Aby zaimportować notatki z Evernote, musisz wyeksportować notatnik Evernote jako ENEX. Kliknij Pomoc, aby uzyskać więcej informacji.\nJeśli masz już plik ENEX, kliknij Przywracanie i wybierz go.</string>
|
||||
<string name="evernote_help">Aby zaimportować notatki z Evernote, musisz wyeksportować notatnik Evernote jako ENEX. Kliknij Pomoc, aby uzyskać więcej informacji.\nJeśli masz już plik ENEX, kliknij Importuj i wybierz go.</string>
|
||||
<string name="every">Każde</string>
|
||||
<string name="export">Eksportuj</string>
|
||||
<string name="export_backup">Wykonaj kopię zapasową</string>
|
||||
|
@ -161,13 +151,11 @@
|
|||
<string name="folder">Folder</string>
|
||||
<string name="follow_system">Systemowy</string>
|
||||
<string name="google_keep">Google Keep</string>
|
||||
<string name="google_keep_help">Aby zaimportować notatki z Google Keep, musisz pobrać plik ZIP Google Takeout. Wybierz tylko dane „Keep”. Kliknij Pomoc, aby uzyskać więcej informacji.\nJeśli masz już plik ZIP Takeout, kliknij Przywracanie i wybierz plik ZIP.</string>
|
||||
<string name="google_keep_help">Aby zaimportować notatki z Google Keep, musisz pobrać plik ZIP Google Takeout. Wybierz tylko dane „Keep”. Kliknij Pomoc, aby uzyskać więcej informacji.\nJeśli masz już plik ZIP Takeout, kliknij Importuj i wybierz plik ZIP.</string>
|
||||
<string name="grid">Siatka</string>
|
||||
<string name="help">Pomoc</string>
|
||||
<string name="hours">Godzin</string>
|
||||
<string name="image_format_not_supported">Format obrazu nie jest obsługiwany</string>
|
||||
<string name="images_hidden_in_overview">Po włączeniu tej opcji obrazy notatek będą ukryte w przeglądzie</string>
|
||||
<string name="images_hidden_in_overview_title">Ukryj obrazy w przeglądzie</string>
|
||||
<string name="import_action">Przywracanie</string>
|
||||
<string name="import_backup">Przywróć kopię zapasową</string>
|
||||
<string name="import_backup_password_hint">Jeśli kopia zapasowa nie jest chroniona hasłem, po prostu naciśnij Importuj, w przeciwnym razie wprowadź prawidłowe hasło.</string>
|
||||
|
@ -179,8 +167,6 @@
|
|||
<string name="imported_files">Przywrócono pliki</string>
|
||||
<string name="imported_notes">Przywrócono notatki</string>
|
||||
<plurals name="imported_notes">
|
||||
<item quantity="few">Przywrócono %1$s notatki</item>
|
||||
<item quantity="many">Przywrócono %1$s notatek</item>
|
||||
<item quantity="one">Przywrócono %1$s notatkę</item>
|
||||
<item quantity="other">Przywrócono %1$s notatek</item>
|
||||
</plurals>
|
||||
|
@ -197,8 +183,6 @@
|
|||
<string name="invalid_link">Skopiuj właściwy link do schowka</string>
|
||||
<string name="italic">Kursywa</string>
|
||||
<string name="item">Element</string>
|
||||
<string name="json_files">Pliki JSON</string>
|
||||
<string name="json_files_help">Aby zaimportować notatki z plików JSON (pojedynczy plik lub folder), kliknij Przywracanie. Każdy prawidłowy plik JSON jest importowany jako osobna notatka, a nazwa pliku staje się tytułem notatki.</string>
|
||||
<string name="label_exists">Etykieta już istnieje</string>
|
||||
<string name="label_visibility">Ukryj/pokaż etykietę w panelu nawigacyjnym</string>
|
||||
<string name="labels">Etykieta</string>
|
||||
|
@ -222,13 +206,11 @@
|
|||
<string name="medium">Średni</string>
|
||||
<string name="minutes">Minut</string>
|
||||
<string name="modified_date">Zmodyfikowano</string>
|
||||
<string name="monospace">Stała szerokość</string>
|
||||
<string name="monospace">Monospace</string>
|
||||
<string name="monthly">Miesięcznie</string>
|
||||
<string name="months">Miesięcy</string>
|
||||
<string name="more">%1$d więcej</string>
|
||||
<plurals name="more_files">
|
||||
<item quantity="few">…%1$d pliki więcej</item>
|
||||
<item quantity="many">…%1$d plików więcej</item>
|
||||
<item quantity="one">…%1$d plik więcej</item>
|
||||
<item quantity="other">…%1$d plików więcej</item>
|
||||
</plurals>
|
||||
|
@ -247,7 +229,7 @@
|
|||
<string name="pin">Przypnij</string>
|
||||
<string name="pinned">Przypięte</string>
|
||||
<string name="plain_text_files">Zwykłe pliki tekstowe</string>
|
||||
<string name="plain_text_files_help">Aby zaimportować Notatki z plików tekstowych (pojedynczy plik lub folder), kliknij Przywracanie. Każdy plik jest importowany jako osobna notatka, a nazwa pliku staje się tytułem notatki. Jeśli treść tekstu zaczyna się od składni listy (np. Markdown „- [x]”, składnia NotallyX „[✓]” lub „*”, „-”), zostanie ona przekonwertowana na notatkę listy.</string>
|
||||
<string name="plain_text_files_help">Aby zaimportować Notatki z plików tekstowych (pojedynczy plik lub folder), kliknij Importuj. Każdy plik jest importowany jako osobna notatka, a nazwa pliku staje się tytułem notatki. Jeśli treść tekstu zaczyna się od składni listy (np. Markdown „- [x]”, składnia NotallyX „[✓]” lub „*”, „-”), zostanie ona przekonwertowana na notatkę listy.</string>
|
||||
<string name="play">Nagrywaj</string>
|
||||
<string name="please_grant_notally_alarm">Zezwól NotallyX na wysyłanie przypomnień</string>
|
||||
<string name="please_grant_notally_audio">Zezwól NotallyX na nagrywanie dźwięku. Nagrania nigdy nie opuszczą Twojego urządzenia</string>
|
||||
|
@ -255,7 +237,6 @@
|
|||
<string name="please_grant_notally_notification_auto_backup">Jeśli automatyczna kopia zapasowa nie powiedzie się, możesz otrzymać powiadomienie, jeśli zezwolisz NotallyX na wysyłanie powiadomień</string>
|
||||
<string name="previous">Wstecz</string>
|
||||
<string name="rate">Oceń aplikację</string>
|
||||
<string name="read_only">Tylko do odczytu</string>
|
||||
<string name="ready_to_record">Oczekiwanie na nagrywanie</string>
|
||||
<string name="record_audio">Nagrywaj</string>
|
||||
<string name="recording">Nagrywanie…</string>
|
||||
|
@ -274,8 +255,6 @@
|
|||
<string name="restart_app">Uruchom ponownie aplikację</string>
|
||||
<string name="restore">Przywróć</string>
|
||||
<plurals name="restored_selected_notes">
|
||||
<item quantity="few">Przywrócono %1$d notatki</item>
|
||||
<item quantity="many">Przywrócono %1$d notatek</item>
|
||||
<item quantity="one">Przywrócono %1$d notatkę</item>
|
||||
<item quantity="other">Przywrócono %1$d notatek</item>
|
||||
</plurals>
|
||||
|
@ -312,13 +291,10 @@
|
|||
<string name="text_default">Domyślny</string>
|
||||
<string name="text_size">Rozmiar tekstu</string>
|
||||
<string name="theme">Motyw</string>
|
||||
<string name="theme_use_dynamic_colors">Użyj kolorów tapety systemu</string>
|
||||
<string name="title">Tytuł</string>
|
||||
<string name="to_record_audio">Aby nagrywać dźwięk, zezwól NotallyX na dostęp do swojego mikrofonu. Dotknij Ustawienia > Uprawnienia i włącz Mikrofon</string>
|
||||
<string name="unarchive">Cofnij archiwizację</string>
|
||||
<plurals name="unarchived_selected_notes">
|
||||
<item quantity="few">Odarchiwizowano %1$d notatki</item>
|
||||
<item quantity="many">Odarchiwizowano %1$d notatek</item>
|
||||
<item quantity="one">Odarchiwizowano %1$d notatkę</item>
|
||||
<item quantity="other">Odarchiwizowano %1$d notatek</item>
|
||||
</plurals>
|
||||
|
|
|
@ -1,334 +1,77 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="about">О приложении</string>
|
||||
<string name="add_images">Добавить изображение</string>
|
||||
<string name="add_item">Добавить пункт</string>
|
||||
<string name="add_label">Добавить метку</string>
|
||||
<string name="add_reminder">Добавить напоминание</string>
|
||||
<string name="adding_files">Добавление файлов</string>
|
||||
<string name="adding_images">Добавление изображений</string>
|
||||
<string name="all">Все</string>
|
||||
<string name="appearance">Внешний вид</string>
|
||||
<string name="archive">Архивировать</string>
|
||||
<string name="archived">Архив</string>
|
||||
<plurals name="archived_selected_notes">
|
||||
<item quantity="few">Архивировано %1$d заметки</item>
|
||||
<item quantity="one">Архивирована %1$d заметка</item>
|
||||
<item quantity="other">Архивировано %1$d заметок</item>
|
||||
</plurals>
|
||||
<string name="ascending">По возрастанию</string>
|
||||
<string name="attach_file">Прикрепить файл</string>
|
||||
<string name="audio_recordings">Аудиозаписи</string>
|
||||
<string name="auto_backup">Автобэкапы</string>
|
||||
<string name="auto_backup_error_message">Ошибка при авто-резервной копии: \n\'%1$s\'\nПроверьте настройки или сообщите об ошибке</string>
|
||||
<string name="auto_backup_failed">Сбой авто-резервирования NotallyX</string>
|
||||
<string name="auto_backup_last">Последняя резервная копия</string>
|
||||
<string name="auto_backup_on_save">Создавать резервную копию при выходе (авто)</string>
|
||||
<string name="auto_backup_on_save_hint">При включении этой функции в папке резервных копий (Папка резервных копий) автоматически создаётся архив NotallyX_AutoBackup.zip при выходе из заметки.\nЭто может повлиять на производительность</string>
|
||||
<string name="auto_backups_folder">Папка резервных копий</string>
|
||||
<string name="auto_backups_folder_hint">Папка, в которой будут храниться резервные копии</string>
|
||||
<string name="auto_backups_folder_rechoose">Необходимо повторно указать папку для резервных копий для доступа NotallyX.\nМожно отменить и пропустить импорт папки резервных копий</string>
|
||||
<string name="auto_backups_folder_set">Сначала укажите папку для резервных копий</string>
|
||||
<string name="auto_save_after_idle_time">Автосохранение заметки после указанного времени бездействия</string>
|
||||
<string name="auto_sort_by_checked">Сортировать отмеченные элементы в конец</string>
|
||||
<string name="back">Назад</string>
|
||||
<string name="backup">Резервная копия</string>
|
||||
<string name="backup_password">Пароль для резервной копии</string>
|
||||
<string name="backup_password_hint">При включении этой функции все новые ZIP-архивы резервных копий буду зашифрованы и защищены паролем</string>
|
||||
<string name="backup_period_days">Интервал авторезервирования (в днях)</string>
|
||||
<string name="backup_periodic">Переодические резервные копии</string>
|
||||
<string name="backup_periodic_hint">При включении этой функции резервные копии будут автоматически сохраняться в указанную папку.\nФункция может не работать при включенном режиме энергосбережения</string>
|
||||
<string name="behaviour">Биометрия</string>
|
||||
<string name="biometric_lock">Блокировать приложение с помощью биометрии или PIN-кода</string>
|
||||
<string name="biometrics_disable_success">Биометрическая защита/PIN-код отключены</string>
|
||||
<string name="biometrics_failure">Ошибка аутентификации по Биометрии/PIN-коду</string>
|
||||
<string name="biometrics_no_support">На устройстве нет биометрических функций</string>
|
||||
<string name="biometrics_not_setup">Биометрия/PIN-код ещё не настроены</string>
|
||||
<string name="biometrics_setup_success">Защита по Биометрии/PIN-коду включена</string>
|
||||
<string name="bold">Жирный</string>
|
||||
<string name="calculating">Вычисление…</string>
|
||||
<string name="cancel">Отменить</string>
|
||||
<plurals name="cant_add_files">
|
||||
<item quantity="few">Невозможно добавить %1$d файла</item>
|
||||
<item quantity="one">Невозможно добавить %1$d файл</item>
|
||||
<item quantity="other">Невозможно добавить %1$d файлов</item>
|
||||
</plurals>
|
||||
<plurals name="cant_add_images">
|
||||
<item quantity="few">Невозможно добавить %1$d изображения</item>
|
||||
<item quantity="one">Невозможно добавить %1$d изображение</item>
|
||||
<item quantity="other">Невозможно добавить %1$d изображений</item>
|
||||
</plurals>
|
||||
<string name="cant_find_folder">Папка не найдена. Возможно, она была перемещена или удалена</string>
|
||||
<string name="cant_find_note">Заметка не найдена. Возможно она была удалена</string>
|
||||
<string name="cant_load_file">Файл не загружен. Возможно, он был перемещён или удалён</string>
|
||||
<string name="cant_load_image">Изображение не загружено. Проверьте, не было ли оно удалено</string>
|
||||
<string name="cant_open_link">Невозможно открыть ссылку</string>
|
||||
<string name="change_color">Изменить цвет</string>
|
||||
<string name="change_color_message">Выберите цвет или создайте новый.\nЦвет можно изменить долгим нажатием.</string>
|
||||
<string name="change_note">Изменить заметку</string>
|
||||
<string name="check_all_items">Выделить всё</string>
|
||||
<string name="choose_another_folder">Выбрать другую папку</string>
|
||||
<string name="choose_folder">Выбрать папку</string>
|
||||
<string name="choose_other_app">Выберите приложение для импорта</string>
|
||||
<string name="clear">Очистить</string>
|
||||
<string name="clear_data">Очистить данные</string>
|
||||
<string name="clear_data_message">Все Заметки, Изображения, Файлы и Аудиозаписи будут навсегда удалены</string>
|
||||
<string name="clear_formatting">Стандартный стиль</string>
|
||||
<string name="cleared_data">Все данные удалены</string>
|
||||
<string name="color">Цвет</string>
|
||||
<string name="color_exists">Этот цвет уже существует!</string>
|
||||
<string name="content_density">Плотность контента</string>
|
||||
<string name="continue_">Продолжить</string>
|
||||
<string name="convert_to_list_note">Конвертировать в Список</string>
|
||||
<string name="convert_to_text_note">Конвертировать в Заметку</string>
|
||||
<string name="copied_link">Ссылка скопирована в буфер обмена</string>
|
||||
<string name="copy">Копировать</string>
|
||||
<string name="crash_message">Произошла непредвиденная ошибка.\nПриносим извинения за причиненные неудобства.</string>
|
||||
<string name="create_github_issue">Сообщить об ошибке на GitHub</string>
|
||||
<string name="creation_date">Создано</string>
|
||||
<string name="custom">Пользовтаельский</string>
|
||||
<string name="daily">Дни</string>
|
||||
<string name="dark">Тёмная</string>
|
||||
<string name="data_in_public">Сохранять данные в общедоступной папке</string>
|
||||
<string name="data_in_public_message">При включении этой функции внутренняя база данных приложения будет перенесена в его общедоступную папку (Android/media/com.philkes.notallyx).\nЭто позволит синхронизировать данные NotallyX между устройствами с помощью приложений для синхронизации файлов.</string>
|
||||
<string name="date">Дата</string>
|
||||
<string name="date_format">Формат даты</string>
|
||||
<string name="date_format_apply_in_note_view">Применять и в просмотре заметки</string>
|
||||
<string name="date_format_hint">Применяет выбранный формат даты в общем списке заметок</string>
|
||||
<string name="days">Дней</string>
|
||||
<string name="delete">Удалить</string>
|
||||
<string name="delete_all">Удалить всё</string>
|
||||
<string name="delete_all_notes">Удалить все заметки\?</string>
|
||||
<string name="delete_audio_recording_forever">Удалить все аудиозаписи\?</string>
|
||||
<string name="delete_checked_items">Удалить выбранные элементы</string>
|
||||
<string name="delete_color_message">Каким цветом заменить текущий цвет заметок\?</string>
|
||||
<string name="delete_file">Удалить файл \'%1$s\'\?</string>
|
||||
<string name="delete_forever">Удалить навсегда</string>
|
||||
<string name="delete_image_forever">Удалить изображение навсегда\?</string>
|
||||
<string name="delete_label">Удалить метку\?</string>
|
||||
<string name="delete_note_forever">Удалить заметку навсегда\?</string>
|
||||
<string name="delete_reminder">Удалить напоминание\?</string>
|
||||
<string name="delete_selected_notes">Удалить выбранные заметки\?</string>
|
||||
<string name="deleted">Удалённые</string>
|
||||
<plurals name="deleted_selected_notes">
|
||||
<item quantity="few">Удалено %1$d заметки</item>
|
||||
<item quantity="one">Удалена %1$d заметка</item>
|
||||
<item quantity="other">Удалено %1$d заметок</item>
|
||||
</plurals>
|
||||
<string name="deleting_files">Удаление файлов</string>
|
||||
<string name="deleting_images">Удаление изображений</string>
|
||||
<string name="descending">По убыванию</string>
|
||||
<string name="disable">Отключить</string>
|
||||
<string name="disable_data_in_public">Переместить данные во внутреннюю папку</string>
|
||||
<string name="disable_lock_description">Это также расшифрует базу данных</string>
|
||||
<string name="disable_lock_title">Отключить защиту по Биометрии/PIN-коду</string>
|
||||
<string name="disabled">Отключено</string>
|
||||
<string name="disallow_screenshots">Запретить создание скриншотов</string>
|
||||
<string name="discard">Отменить</string>
|
||||
<string name="display_text">Текст для отображения</string>
|
||||
<string name="donate">Сделать пожертвование</string>
|
||||
<string name="drag_handle">Перетащить</string>
|
||||
<string name="edit">Редактировать</string>
|
||||
<string name="edit_color">Изменить цвет</string>
|
||||
<string name="edit_label">Изменить метку</string>
|
||||
<string name="edit_link">Изменить ссылку</string>
|
||||
<string name="edit_reminders">Изменить напоминания</string>
|
||||
<string name="elapsed">Просроченные</string>
|
||||
<string name="empty_labels">Еще нет меток. Создать\?</string>
|
||||
<string name="empty_labels">Еще нет меток, создать\?</string>
|
||||
<string name="empty_list">Пустой список</string>
|
||||
<string name="empty_note">Пустая заметка</string>
|
||||
<string name="empty_reminders">Напоминаний нет. Создать\?</string>
|
||||
<string name="enable_lock_description">Это также зашифрует базу данных</string>
|
||||
<string name="enable_lock_title">Включить защиту по Биометрии/PIN-коду</string>
|
||||
<string name="enabled">Включено</string>
|
||||
<string name="error_while_renaming_file">Ошибка переименования файла</string>
|
||||
<string name="error_while_renaming_image">Ошибка переименования изображения</string>
|
||||
<string name="evernote">Evernote</string>
|
||||
<string name="evernote_help">Чтобы импортировать заметки из Evernote, экспортируйте блокнот в формате ENEX. Нажмите \"Помощь\" для инструкций.\n\nЕсли файл ENEX уже готов, выберите \"Импорт\"</string>
|
||||
<string name="every">Каждый</string>
|
||||
<string name="export">Экспорт</string>
|
||||
<string name="export_backup">Экспорт резервной копии</string>
|
||||
<string name="export_settings">Экспорт настроек</string>
|
||||
<string name="export_settings_failure">Не удалось экспортировать настройки. Возможно, указан недопустимый путь</string>
|
||||
<string name="export_settings_message">Все настройки будут сохранены в JSON-файл для последующего импорта.\n\nОбратите внимание: зашифрованные данные (пароль авторезерва и биометрический ключ) не экспортируются.</string>
|
||||
<string name="export_settings_success">Настройки успешно экспортированы</string>
|
||||
<string name="exporting_backup">Экспорт резервной копии</string>
|
||||
<string name="extracted_files">Файлы извлечены</string>
|
||||
<string name="export">Экспортировать</string>
|
||||
<string name="export_backup">Экспортировать</string>
|
||||
<string name="filter">Фильтры</string>
|
||||
<string name="folder">Папка</string>
|
||||
<string name="follow_system">Как в системе</string>
|
||||
<string name="google_keep">Google Keep</string>
|
||||
<string name="google_keep_help">Для импорта из Google Keep скачайте архив Takeout (только данные \"Keep\"). Нажмите \"Помощь\" для подробностей.\n\nЕсли архив уже есть, выберите его через \"Импорт\"</string>
|
||||
<string name="grid">Сетка</string>
|
||||
<string name="help">Помощь</string>
|
||||
<string name="hours">Часов</string>
|
||||
<string name="image_format_not_supported">Формат изображения не поддерживыется</string>
|
||||
<string name="images_hidden_in_overview">Если эта функция включена, изображения заметок будут скрыты из общего списка.</string>
|
||||
<string name="images_hidden_in_overview_title">Скрыть изображения в общем списке</string>
|
||||
<string name="import_action">Импорт</string>
|
||||
<string name="import_backup">Импорт резервной копии</string>
|
||||
<string name="import_backup_password_hint">Если резервная копия не защищена паролем, нажмите \"Импорт\". В противном случае введите пароль.</string>
|
||||
<string name="import_other">Импорт заметок из других приложений</string>
|
||||
<string name="import_settings">Импорт настроек</string>
|
||||
<string name="import_settings_failure">Не удалось импортировать настройки. Вы выбрали правильный файл\?</string>
|
||||
<string name="import_settings_message">Для импорта настроек выберите корректный JSON-файл настроек NotallyX. </string>
|
||||
<string name="import_settings_success">Настройки успешно импортированы</string>
|
||||
<string name="imported_files">Файлы импортированы</string>
|
||||
<string name="imported_notes">Заметки импортированы</string>
|
||||
<plurals name="imported_notes">
|
||||
<item quantity="few">Импортировано %1$s заметки</item>
|
||||
<item quantity="one">Импортирована %1$s заметка</item>
|
||||
<item quantity="other">Импортировано %1$s заметок</item>
|
||||
</plurals>
|
||||
<string name="importing_backup">Импорт резервной копии</string>
|
||||
<string name="insert_an_sd_card_audio">Вставьте SD-карту для записи аудио</string>
|
||||
<string name="insert_an_sd_card_files">Для добавления файлов вставьте SD-карту</string>
|
||||
<string name="insert_an_sd_card_images">Вставьте SD-карту, чтобы загрузить изображение</string>
|
||||
<string name="install_a_browser">Чтобы открыть ссылку, установите браузер</string>
|
||||
<string name="install_an_email">Установите клиент почты для отправки отзыва</string>
|
||||
<string name="invalid_backup">Некорректная резервная копия</string>
|
||||
<string name="invalid_evernote">Недопустимый файл Evernote (ENEX)</string>
|
||||
<string name="invalid_google_keep">Некорректный ZIP-архив Google Takeout</string>
|
||||
<string name="invalid_image">Изображение повреждено</string>
|
||||
<string name="invalid_link">Скопируйте рабочую ссылку в буфер обмена</string>
|
||||
<string name="import_backup">Импортировать</string>
|
||||
<string name="italic">Курсив</string>
|
||||
<string name="item">Пункт</string>
|
||||
<string name="json_files">JSON файлы</string>
|
||||
<string name="json_files_help">Для импорта заметок из JSON-файлов (отдельный файл или папка) нажмите \"Импорт\". Каждый корректный JSON-файл будет преобразован в отдельную заметку, где имя файла станет её заголовком</string>
|
||||
<string name="label_exists">Метка уже существует</string>
|
||||
<string name="label_visibility">Скрыть/показать метку в панели навигации</string>
|
||||
<string name="labels">Метки</string>
|
||||
<string name="labels_hidden_in_overview">При включении этой функции метки заметок будут скрыты в общем списке</string>
|
||||
<string name="labels_hidden_in_overview_title">Скрывать метки в общем списке</string>
|
||||
<string name="large">Большой</string>
|
||||
<string name="libraries">Библиотеки</string>
|
||||
<string name="light">Светлая</string>
|
||||
<string name="link">Ссылка</string>
|
||||
<string name="link_note">Связать заметку</string>
|
||||
<string name="list">Список</string>
|
||||
<string name="list_item_auto_sort">Сортировать элементы списка</string>
|
||||
<string name="locked">Заблокировано</string>
|
||||
<string name="make_feature_request">Запросить новую функцию</string>
|
||||
<string name="make_list">Создать список</string>
|
||||
<string name="max_backups">Лимит резервных копий</string>
|
||||
<string name="max_items_to_display">Максимум отображаемых пунктов в списке</string>
|
||||
<string name="max_labels_to_display">Максимум отображаемых меток</string>
|
||||
<string name="max_lines_to_display">Максимум отображаемых строк в заметке</string>
|
||||
<string name="max_lines_to_display_title">Максимум отображаемых строк в заголовке</string>
|
||||
<string name="medium">Средний</string>
|
||||
<string name="minutes">Минуты</string>
|
||||
<string name="modified_date">Изменено</string>
|
||||
<string name="monospace">Моноширинный</string>
|
||||
<string name="monthly">Ежемесячно</string>
|
||||
<string name="months">Месяцы</string>
|
||||
<string name="more">Ещё %1$d</string>
|
||||
<plurals name="more_files">
|
||||
<item quantity="few">...ещё %1$d файла</item>
|
||||
<item quantity="one">...ещё %1$d файл</item>
|
||||
<item quantity="other">...ещё %1$d файлов</item>
|
||||
</plurals>
|
||||
<string name="new_color">Новый цвет</string>
|
||||
<string name="next">Следующий</string>
|
||||
<string name="no_auto_sort">Без автосортировки</string>
|
||||
<string name="none">Отсутствует</string>
|
||||
<string name="note">Заметка</string>
|
||||
<string name="notes">Заметки</string>
|
||||
<string name="notes_sorted_by">Сортировать заметки по</string>
|
||||
<string name="open_link">Открыть ссылку</string>
|
||||
<string name="open_note">Открыть заметку</string>
|
||||
<string name="others">Другие</string>
|
||||
<string name="pause">Пауза</string>
|
||||
<string name="paused">Приостановлено</string>
|
||||
<string name="pin">Закрепить</string>
|
||||
<string name="pinned">Закреплённые</string>
|
||||
<string name="plain_text_files">Текстовые файлы</string>
|
||||
<string name="plain_text_files_help">Для импорта заметок из текстовых файлов (отдельный файл или папка) нажмите \"Импорт\". Каждый файл станет отдельной заметкой — имя файла будет её заголовком. Если текст начинается с элементов списка (например, Markdown \"- [x]\", синтаксис NotallyX \"[~/\", или \"*\", ~), он преобразуется в заметку-список.</string>
|
||||
<string name="play">Играть</string>
|
||||
<string name="please_grant_notally_alarm">Разрешите NotallyX отправлять напоминания</string>
|
||||
<string name="please_grant_notally_audio">Разрешите доступ к микрофону.\nЗаписи остаются на вашем устройстве</string>
|
||||
<string name="please_grant_notally_notification">Разрешите отправку уведомлений</string>
|
||||
<string name="please_grant_notally_notification_auto_backup">При сбое авторезервирования вы получите уведомление, если разрешите их отправку. </string>
|
||||
<string name="previous">Предыдущий</string>
|
||||
<string name="rate">Оценить приложение</string>
|
||||
<string name="read_only">Только чтение</string>
|
||||
<string name="ready_to_record">Готово к записи</string>
|
||||
<string name="record_audio">Запись аудио</string>
|
||||
<string name="recording">Запись…</string>
|
||||
<string name="redo">Вернуть</string>
|
||||
<string name="reminder_no_repetition">Без повтора</string>
|
||||
<string name="reminders">Напоминания</string>
|
||||
<string name="remove_link">Удалить ссылку</string>
|
||||
<string name="repetition">Повтор</string>
|
||||
<string name="repetition_custom">Свой вариант повтора</string>
|
||||
<string name="repetition_value_hint">Значение</string>
|
||||
<string name="report_bug">Сообщить об ошибке/баге</string>
|
||||
<string name="report_crash">Отправить отчёт об ошибке</string>
|
||||
<string name="reset_settings">Сбросить настройки</string>
|
||||
<string name="reset_settings_message">Все настройки будут сброшены к значениям по умолчанию</string>
|
||||
<string name="reset_settings_success">Все настройки успешно сброшены</string>
|
||||
<string name="restart_app">Перезапустить приложение</string>
|
||||
<string name="restore">Восстановить</string>
|
||||
<plurals name="restored_selected_notes">
|
||||
<item quantity="few">Восстановлено %1$d заметки</item>
|
||||
<item quantity="one">Восстановлена %1$d заметка</item>
|
||||
<item quantity="other">Восстановлено %1$d заметок</item>
|
||||
</plurals>
|
||||
<string name="resume">Повторить</string>
|
||||
<string name="save">Сохранить</string>
|
||||
<string name="save_recording">Сохранить аудиозапись\?</string>
|
||||
<string name="save_to_device">Сохранить на устройстве</string>
|
||||
<string name="saved_to_device">Сохранено на устройстве</string>
|
||||
<string name="saved_to_notally">Сохранено в NotallyX</string>
|
||||
<string name="search">Поиск</string>
|
||||
<string name="security">Безопасность</string>
|
||||
<string name="select_all">Выбрать всё</string>
|
||||
<string name="select_labels">Выбрать метки</string>
|
||||
<string name="select_note">Выбрать заметки</string>
|
||||
<string name="send_feedback">Сообщить о проблеме</string>
|
||||
<string name="settings">Настройки</string>
|
||||
<string name="share">Поделиться</string>
|
||||
<string name="skip">Пропустить</string>
|
||||
<string name="small">Маленький</string>
|
||||
<string name="something_went_wrong">Что-то пошло не так. Пожалуйста, повторите попытку</string>
|
||||
<string name="sort_direction">Порядок сортировки</string>
|
||||
<string name="source_code">Исходный код</string>
|
||||
<string name="start">Старт</string>
|
||||
<string name="start_view">Стартовый экран</string>
|
||||
<string name="start_view_hint">Выберите, какой экран/ярлык показывать при запуске.\nПо умолчанию — основной список заметок</string>
|
||||
<string name="stop">Стоп</string>
|
||||
<string name="strikethrough">Перечёркнутый</string>
|
||||
<string name="take_note">Создать заметку</string>
|
||||
<string name="tap_for_more_options">Нажмите для подробностей</string>
|
||||
<string name="tap_to_set_up">Нажмите для настройки</string>
|
||||
<string name="text_default">По умолчанию</string>
|
||||
<string name="text_size">Размер текста</string>
|
||||
<string name="theme">Тема</string>
|
||||
<string name="theme_use_dynamic_colors">Использовать цвета обоев</string>
|
||||
<string name="title">Заголовок</string>
|
||||
<string name="to_record_audio">Что-бы записывать аудиозаписи, разрешите NotallyX доступ к микрофону</string>
|
||||
<string name="unarchive">Разархивировать</string>
|
||||
<plurals name="unarchived_selected_notes">
|
||||
<item quantity="few">Извлечено %1$d заметки</item>
|
||||
<item quantity="one">Извлечено %1$d заметка</item>
|
||||
<item quantity="other">Извлечено %1$d заметок</item>
|
||||
</plurals>
|
||||
<string name="uncheck_all_items">Очистить выбор</string>
|
||||
<string name="undo">Вернуть</string>
|
||||
<string name="unknown_error">Неизвестная ошибка</string>
|
||||
<string name="unknown_name">Неизвестное имя</string>
|
||||
<string name="unlabeled">Без названия</string>
|
||||
<string name="unlock">Разблокировка по Биометрии/PIN-коду</string>
|
||||
<string name="unlock_with_biometrics_not_setup">Ранее вы включили биометрическую защиту, но сейчас на устройстве не настроены биометрия или PIN-код.\n\nНажмите «Отключить», чтобы снять блокировку, или настройте биометрию/PIN-код заново</string>
|
||||
<string name="unpin">Открепить</string>
|
||||
<string name="upcoming">Предстоящие</string>
|
||||
<string name="updated_link">Обновить ссылку</string>
|
||||
<string name="view">Вид</string>
|
||||
<string name="view_file">Посмотреть файл</string>
|
||||
<string name="view_note">Посмотреть заметку…</string>
|
||||
<string name="weekly">Еженедельный</string>
|
||||
<string name="weeks">Недели</string>
|
||||
<string name="wrong_password">Неверный пароль</string>
|
||||
<string name="yearly">Ежегодный</string>
|
||||
<string name="years">Года</string>
|
||||
<string name="your_notes_associated">Ваши заметки, связанные с этой меткой, не будут удалены</string>
|
||||
</resources>
|
||||
|
|
|
@ -54,9 +54,4 @@
|
|||
<item name="android:navigationBarColor">?attr/colorSurface</item>
|
||||
<item name="android:windowLightNavigationBar">true</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeOverlay.App.BottomSheetDialog" parent="ThemeOverlay.Material3.BottomSheetDialog">
|
||||
<item name="bottomSheetStyle">@style/ModalBottomSheet</item>
|
||||
<item name="android:windowIsFloating">false</item>
|
||||
</style>
|
||||
</resources>
|
|
@ -24,6 +24,7 @@
|
|||
<string name="auto_backup_last">上次备份</string>
|
||||
<string name="auto_backup_on_save">保存笔记时自动备份</string>
|
||||
<string name="auto_backup_on_save_hint">启用本选项后,每当保存笔记时都会在所配置的”备份文件夹“中自动创建一个备份文件(”NotallyX_AutoBackup.zip)。请注意这可能影响性能</string>
|
||||
<string name="auto_backup_period">自动备份周期</string>
|
||||
<string name="auto_backups_folder">备份文件夹</string>
|
||||
<string name="auto_backups_folder_hint">保存所有自动备份文件的文件夹</string>
|
||||
<string name="auto_backups_folder_rechoose">你需要重新选择备份文件夹,这样 NotallyX 有写入它的权限。你也可以按:取消“跳过导入备份文件夹的值</string>
|
||||
|
@ -93,6 +94,7 @@
|
|||
<string name="date_format_apply_in_note_view">同样应用于笔记视图</string>
|
||||
<string name="date_format_hint">将所选日期格式应用于笔记概览</string>
|
||||
<string name="days">天</string>
|
||||
<string name="default_note_view_mode">默认的笔记查看模式</string>
|
||||
<string name="delete">删除</string>
|
||||
<string name="delete_all">删除全部</string>
|
||||
<string name="delete_all_notes">删除全部笔记?</string>
|
||||
|
@ -118,7 +120,6 @@
|
|||
<string name="disable_lock_description">这也会解密数据据</string>
|
||||
<string name="disable_lock_title">停用生物特征/PIN锁</string>
|
||||
<string name="disabled">禁用</string>
|
||||
<string name="disallow_screenshots">禁止截屏</string>
|
||||
<string name="discard">取消</string>
|
||||
<string name="display_text">要展示的我呢本</string>
|
||||
<string name="donate">捐赠</string>
|
||||
|
@ -158,8 +159,6 @@
|
|||
<string name="help">帮助</string>
|
||||
<string name="hours">小时</string>
|
||||
<string name="image_format_not_supported">不支持该图片格式</string>
|
||||
<string name="images_hidden_in_overview">如果启用此选项,则注释的图像将不会显示在概览中。</string>
|
||||
<string name="images_hidden_in_overview_title">在概览中隐藏图片</string>
|
||||
<string name="import_action">导入</string>
|
||||
<string name="import_backup">导入备份</string>
|
||||
<string name="import_backup_password_hint">如果你的备份文件没有密码保护,只需按下“导入”即可。如有,起输入正确的密码</string>
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
<string name="auto_backup_last">最近的備份</string>
|
||||
<string name="auto_backup_on_save">筆記上的備份會自動儲存</string>
|
||||
<string name="auto_backup_on_save_hint">透過啟用此功能,每當儲存筆記時,都會在選擇的\"備份資料夾\"中自動建立備份(\"NotallyX_AutoBackup.zip\")。\n請注意這可能會影響效能</string>
|
||||
<string name="auto_backup_period">自動備份週期</string>
|
||||
<string name="auto_backups_folder">備份資料夾</string>
|
||||
<string name="auto_backups_folder_hint">所有自動備份都儲存於其中的資料夾。</string>
|
||||
<string name="auto_backups_folder_rechoose">您需要重新選擇備份資料夾,以便 NotallyX 有權限寫入該資料夾。\n您也可以按取消跳過匯入備份資料夾</string>
|
||||
|
@ -134,8 +135,6 @@
|
|||
<string name="help">幫助</string>
|
||||
<string name="hours">小時</string>
|
||||
<string name="image_format_not_supported">不支持的圖片格式</string>
|
||||
<string name="images_hidden_in_overview">啟用此功能後,筆記的圖像將隱藏在概覽中。</string>
|
||||
<string name="images_hidden_in_overview_title">在概覽中隱藏圖片</string>
|
||||
<string name="import_action">匯入</string>
|
||||
<string name="import_backup">匯入備份</string>
|
||||
<string name="import_backup_password_hint">如果您的備份沒有密碼保護,只需按匯入,否則請輸入正確的密碼。</string>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
<string name="auto_backup_last">Last Backup</string>
|
||||
<string name="auto_backup_on_save">Backup on exit Note automatically</string>
|
||||
<string name="auto_backup_on_save_hint">By enabling this, a backup (\"NotallyX_AutoBackup.zip\") is automatically created in the configured \"Backups Folder\" whenever a note is exited.\nBe aware this might affect performance</string>
|
||||
<string name="auto_backup_period">Auto backup period</string>
|
||||
<string name="auto_backups_folder">Backups Folder</string>
|
||||
<string name="auto_backups_folder_hint">Folder in which all auto backups will be stored in.</string>
|
||||
<string name="auto_backups_folder_rechoose">You need to re-choose your Backups Folder so that NotallyX has permission to write to it.\nYou can also press cancel to skip importing Backups Folder value</string>
|
||||
|
@ -95,6 +96,7 @@
|
|||
<string name="date_format_apply_in_note_view">Also apply in Note View</string>
|
||||
<string name="date_format_hint">Applies selected date format in Notes Overview</string>
|
||||
<string name="days">Days</string>
|
||||
<string name="default_note_view_mode">Default Note View Mode</string>
|
||||
<string name="delete">Delete</string>
|
||||
<string name="delete_all">Delete all</string>
|
||||
<string name="delete_all_notes">Delete all notes\?</string>
|
||||
|
@ -121,7 +123,6 @@
|
|||
<string name="disable_lock_description">This will also decrypt the database</string>
|
||||
<string name="disable_lock_title">Disable lock via Biometric/PIN</string>
|
||||
<string name="disabled">Disabled</string>
|
||||
<string name="disallow_screenshots">Disallow Screenshots</string>
|
||||
<string name="discard">Discard</string>
|
||||
<string name="display_text">Text to display</string>
|
||||
<string name="donate">Make a Donation</string>
|
||||
|
@ -161,8 +162,6 @@
|
|||
<string name="help">Help</string>
|
||||
<string name="hours">Hours</string>
|
||||
<string name="image_format_not_supported">Image format not supported</string>
|
||||
<string name="images_hidden_in_overview">By enabling this, the notes’ images will be hidden in the overview</string>
|
||||
<string name="images_hidden_in_overview_title">Hide Images in Overview</string>
|
||||
<string name="import_action">Import</string>
|
||||
<string name="import_backup">Import backup</string>
|
||||
<string name="import_backup_password_hint">If your backup is not password-protected simply press Import, otherwise enter the correct password.</string>
|
||||
|
|
|
@ -124,7 +124,6 @@
|
|||
|
||||
<style name="ThemeOverlay.App.BottomSheetDialog" parent="ThemeOverlay.Material3.BottomSheetDialog">
|
||||
<item name="bottomSheetStyle">@style/ModalBottomSheet</item>
|
||||
<item name="android:windowIsFloating">true</item>
|
||||
</style>
|
||||
|
||||
<style name="ModalBottomSheet" parent="Widget.Material3.BottomSheet.Modal">
|
||||
|
|
Binary file not shown.
|
@ -1,8 +0,0 @@
|
|||
* Möglichkeit Screenshots zu verbieten
|
||||
|
||||
* Fix Android 7 Kompatibilität
|
||||
|
||||
* Fix Links öffnen
|
||||
|
||||
* Fix abgehakte Elemente löschen
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
* Add disallow screenshots security setting
|
||||
|
||||
* Fix Android 7 compatibility issues
|
||||
|
||||
* Fix opening links
|
||||
|
||||
* Fix delete checked items crash
|
||||
|
|
@ -20,6 +20,6 @@ org.gradle.jvmargs=-Xmx1536m -XX:+UseParallelGC
|
|||
org.gradle.parallel=true
|
||||
android.experimental.enableNewResourceShrinker.preciseShrinking=true
|
||||
android.defaults.buildfeatures.buildconfig=true
|
||||
app.lastVersionName=7.4.0
|
||||
app.versionCode=7410
|
||||
app.versionName=7.4.1
|
||||
app.lastVersionName=7.3.0
|
||||
app.versionCode=7310
|
||||
app.versionName=7.3.1
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue