Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
android:name=".activity.security.SetupKeyActivity"
android:exported="false"
android:screenOrientation="locked"
android:theme="@style/AppTheme.NoActionBar" />
android:theme="@style/AppTheme" />
<activity
android:name=".activity.security.AuthActivity"
android:exported="false"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.util.SparseArray;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
Expand All @@ -36,9 +37,11 @@
import app.notesr.activity.exporter.ExportActivity;
import app.notesr.activity.importer.ImportActivity;
import app.notesr.activity.note.editor.OpenNoteActivity;
import app.notesr.activity.security.ChangePasswordOnClick;
import app.notesr.activity.security.GenerateNewKeyOnClick;
import app.notesr.activity.security.LockOnClick;
import app.notesr.activity.security.AuthActivity;
import app.notesr.activity.security.GenerateNewKeyAction;
import app.notesr.activity.security.LockAction;
import app.notesr.core.security.crypto.CryptoManager;
import app.notesr.core.security.crypto.CryptoManagerProvider;
import app.notesr.data.AppDatabase;
import app.notesr.data.DatabaseProvider;
import app.notesr.data.model.Note;
Expand All @@ -47,17 +50,18 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

public final class NotesListActivity extends ActivityBase {

private static final int SEARCH_DELAY = 300;

private final Map<Integer, Consumer<ActivityBase>> menuItemsMap = new HashMap<>();
private final SparseArray<Runnable> menuActions = new SparseArray<>();
private final Map<Long, String> notesIdsMap = new HashMap<>();
private final Handler searchHandler = new Handler(Looper.getMainLooper());

private ActivityResultLauncher<Intent> noteEditorLauncher;
private LockAction lockAction;
private GenerateNewKeyAction generateNewKeyAction;

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand All @@ -70,18 +74,16 @@ protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_note_list);
applyInsets(findViewById(R.id.main));

getOnBackPressedDispatcher()
.addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
LockOnClick lock = new LockOnClick();
lock.accept(NotesListActivity.this);
}
});
CryptoManager cryptoManager = CryptoManagerProvider.getInstance(getApplicationContext());

lockAction = new LockAction(this, cryptoManager);
generateNewKeyAction = new GenerateNewKeyAction(this, cryptoManager);

noteEditorLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(), getOpenNoteResultCallback());

getOnBackPressedDispatcher().addCallback(this, getOnBackPressedCallback());

ListView notesView = findViewById(R.id.notesListView);
FloatingActionButton newNoteButton = findViewById(R.id.addNoteButton);

Expand All @@ -100,20 +102,15 @@ public void handleOnBackPressed() {
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);

Intent importActivityIntent = new Intent(this, ImportActivity.class);
Intent exportActivityIntent = new Intent(this, ExportActivity.class);

getMenuInflater().inflate(R.menu.menu_notes_list, menu);

menuItemsMap.put(R.id.lockAppButton, new LockOnClick());
menuItemsMap.put(R.id.changePasswordMenuItem, new ChangePasswordOnClick());
menuItemsMap.put(R.id.generateNewKeyMenuItem, new GenerateNewKeyOnClick());

menuItemsMap.put(R.id.exportMenuItem, action ->
startActivity(exportActivityIntent));

menuItemsMap.put(R.id.importMenuItem, action ->
startActivity(importActivityIntent));
menuActions.put(R.id.lockAppButton, lockAction::lock);
menuActions.put(R.id.changePasswordMenuItem, this::startChangePasswordActivity);
menuActions.put(R.id.generateNewKeyMenuItem, generateNewKeyAction::startActivity);
menuActions.put(R.id.exportMenuItem,
() -> startActivity(new Intent(this, ExportActivity.class)));
menuActions.put(R.id.importMenuItem,
() -> startActivity(new Intent(this, ImportActivity.class)));

SearchView searchView = (SearchView) menu.findItem(R.id.searchNotesButton).getActionView();
requireNonNull(searchView, "SearchView is null");
Expand All @@ -131,7 +128,7 @@ public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();

if (itemId != R.id.searchNotesButton) {
requireNonNull(menuItemsMap.get(itemId)).accept(this);
requireNonNull(menuActions.get(itemId)).run();
}

return true;
Expand Down Expand Up @@ -250,4 +247,19 @@ private void openNote(String noteId) {

noteEditorLauncher.launch(intent);
}

private void startChangePasswordActivity() {
Intent intent = new Intent(getApplicationContext(), AuthActivity.class)
.putExtra(AuthActivity.EXTRA_MODE, AuthActivity.Mode.CHANGE_PASSWORD.toString());
startActivity(intent);
}

private OnBackPressedCallback getOnBackPressedCallback() {
return new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
lockAction.lock();
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public void authorize() {
}

public void createPassword() {
var password = proceedPasswordSetting();
char[] password = proceedPasswordSetting();

if (password != null) {
var context = activity.getApplicationContext();
Expand All @@ -80,7 +80,7 @@ public void createPassword() {

try {
var passwordBytes = charsToBytes(password, StandardCharsets.UTF_8);
SecretCache.put(SetupKeyActivity.PASSWORD, passwordBytes);
SecretCache.put(SetupKeyActivity.CACHE_KEY_PASSWORD, passwordBytes);
} catch (CharacterCodingException e) {
throw new RuntimeException(e);
}
Expand All @@ -90,11 +90,11 @@ public void createPassword() {
}

public void recoverKey() {
var password = proceedPasswordSetting();
char[] password = proceedPasswordSetting();

if (password != null) {
try {
var hexKey = bytesToChars(SecretCache.take(HEX_KEY),
char[] hexKey = bytesToChars(SecretCache.take(HEX_KEY),
StandardCharsets.UTF_8);

if (hexKey == null) {
Expand All @@ -118,19 +118,19 @@ public void recoverKey() {
}

public void changePassword() {
var password = proceedPasswordSetting();
char[] password = proceedPasswordSetting();

if (password != null) {
try {
var context = activity.getApplicationContext();
var secrets = cryptoManager.getSecrets();
Context context = activity.getApplicationContext();
CryptoSecrets secrets = cryptoManager.getSecrets();
secrets.setPassword(password);

cryptoManager.setSecrets(context, secrets);
secrets.destroy();

showToastMessage(R.string.updated);
activity.startActivity(new Intent(context, NotesListActivity.class));
activity.startActivity(new Intent(context, NotesListActivity.class));
} catch (Exception e) {
throw new RuntimeException(e);
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2026 zHd4
* SPDX-License-Identifier: MIT
*/

package app.notesr.activity.security;

import static app.notesr.core.util.CharUtils.charsToBytes;

import android.content.Context;
import android.content.Intent;

import app.notesr.activity.ActivityBase;
import app.notesr.core.security.SecretCache;
import app.notesr.core.security.crypto.CryptoManager;
import app.notesr.core.security.dto.CryptoSecrets;
import lombok.RequiredArgsConstructor;

import java.nio.charset.CharacterCodingException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

@RequiredArgsConstructor
public final class GenerateNewKeyAction {

private final ActivityBase activity;
private final CryptoManager cryptoManager;

public void startActivity() {
CryptoSecrets secrets = cryptoManager.getSecrets();
char[] passwordChars = Arrays.copyOf(secrets.getPassword(), secrets.getPassword().length);

try {
byte[] passwordBytes = charsToBytes(passwordChars, StandardCharsets.UTF_8);
SecretCache.put(SetupKeyActivity.CACHE_KEY_PASSWORD, passwordBytes);
} catch (CharacterCodingException e) {
throw new RuntimeException(e);
}

secrets.destroy();

Context context = activity.getApplicationContext();
var intent = new Intent(context, SetupKeyActivity.class)
.putExtra(SetupKeyActivity.EXTRA_MODE, KeySetupMode.REGENERATION.toString());
activity.startActivity(intent);
}
}

This file was deleted.

Loading
Loading