From 0718207fe51810668b066ef84b1dcc992c4d46af Mon Sep 17 00:00:00 2001 From: octospacc Date: Sat, 20 Sep 2025 02:13:58 +0200 Subject: [PATCH] Remove old files, Fix crash on Android 4.1, Add font and keyboard mode settings, Fix icon (use PNG), Update some strings --- README.md | 10 +- app/build.gradle | 4 +- app/release/output-metadata.json | 2 +- app/src/main/AndroidManifest.xml | 14 +- .../octt/notetand/BluetoothSyncActivity.java | 797 ------------------ .../org/eu/octt/notetand/CustomActivity.java | 1 - .../org/eu/octt/notetand/MainActivity.java | 23 +- .../org/eu/octt/notetand/MainActivity1.java | 380 --------- .../org/eu/octt/notetand/NoteActivity.java | 90 +- .../org/eu/octt/notetand/ReceiveActivity.java | 28 +- .../org/eu/octt/notetand/SendActivity.java | 19 +- .../eu/octt/notetand/SettingsActivity.java | 118 ++- .../org/eu/octt/notetand/SettingsManager.java | 19 +- .../drawable-v24/ic_launcher_foreground.xml | 30 - .../res/drawable/ic_launcher_background.xml | 170 ---- app/src/main/res/layout/activity_note.xml | 23 +- app/src/main/res/layout/activity_receive.xml | 2 +- .../res/layout/bluetooth_sync_activity.xml | 152 ---- app/src/main/res/layout/main_activity_1.xml | 84 -- app/src/main/res/menu/main_menu.xml | 15 +- app/src/main/res/menu/note_menu.xml | 15 +- app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 6317 bytes app/src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 5186 -> 0 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 8931 bytes .../mipmap-hdpi/ic_launcher_foreground.webp | Bin 5622 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 6317 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 5186 -> 0 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 3616 bytes app/src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 3130 -> 0 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 4685 bytes .../mipmap-mdpi/ic_launcher_foreground.webp | Bin 3136 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3616 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 3130 -> 0 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 9711 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 7788 -> 0 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 14836 bytes .../mipmap-xhdpi/ic_launcher_foreground.webp | Bin 9198 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 9711 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 7788 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 17838 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 13498 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 33161 bytes .../mipmap-xxhdpi/ic_launcher_foreground.webp | Bin 19842 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 17838 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 13498 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 28767 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 20470 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 60983 bytes .../ic_launcher_foreground.webp | Bin 36754 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 28767 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 20470 -> 0 bytes app/src/main/res/values-it/strings.xml | 6 + app/src/main/res/values/colors.xml | 10 - app/src/main/res/values/ids.xml | 5 - app/src/main/res/values/strings.xml | 8 +- 55 files changed, 206 insertions(+), 1819 deletions(-) delete mode 100644 app/src/main/java/org/eu/octt/notetand/BluetoothSyncActivity.java delete mode 100644 app/src/main/java/org/eu/octt/notetand/MainActivity1.java delete mode 100644 app/src/main/res/drawable-v24/ic_launcher_foreground.xml delete mode 100644 app/src/main/res/drawable/ic_launcher_background.xml delete mode 100644 app/src/main/res/layout/bluetooth_sync_activity.xml delete mode 100644 app/src/main/res/layout/main_activity_1.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp delete mode 100644 app/src/main/res/values/colors.xml delete mode 100644 app/src/main/res/values/ids.xml diff --git a/README.md b/README.md index 06dd775..46ce2aa 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,11 @@ # NoteTand -Simple plain-text notes app with Bluetooth sync! \ No newline at end of file +Simple plain-text notes app with Bluetooth sync! + + + + + +
GitLab.comGitHubGitea.it
+ +App Screenshot \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 48f9341..d1c68de 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,7 +8,7 @@ android { defaultConfig { applicationId "org.eu.octt.notetand" - minSdk 10 + minSdk 9 targetSdk 35 versionCode 1 versionName "1.0" @@ -22,7 +22,7 @@ android { } compileOptions { sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } } diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json index 7db3c84..cc98537 100644 --- a/app/release/output-metadata.json +++ b/app/release/output-metadata.json @@ -17,5 +17,5 @@ } ], "elementType": "File", - "minSdkVersionForDexing": 10 + "minSdkVersionForDexing": 9 } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0bd85ac..a7a4fd4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -39,10 +39,6 @@ - - - - - - - + --> diff --git a/app/src/main/java/org/eu/octt/notetand/BluetoothSyncActivity.java b/app/src/main/java/org/eu/octt/notetand/BluetoothSyncActivity.java deleted file mode 100644 index 58037ea..0000000 --- a/app/src/main/java/org/eu/octt/notetand/BluetoothSyncActivity.java +++ /dev/null @@ -1,797 +0,0 @@ -package org.eu.octt.notetand; - -import android.Manifest; -import android.app.Activity; -import android.app.AlertDialog; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothServerSocket; -import android.bluetooth.BluetoothSocket; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; -import android.view.MenuItem; -import android.view.View; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.ListView; -import android.widget.TextView; -import android.widget.Toast; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.UUID; - -public class BluetoothSyncActivity extends Activity { - - private static final String TAG = "BluetoothSync"; - private static final UUID SERVICE_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); - private static final String SERVICE_NAME = "SyncNotesApp"; - private static final int REQUEST_DISCOVERABLE = 2001; - private static final int DISCOVERABLE_DURATION = 300; // 5 minutes - - // Protocol constants - private static final String PROTOCOL_HANDSHAKE = "SYNCNOTES_HANDSHAKE"; - private static final String PROTOCOL_FILE_LIST = "FILE_LIST"; - private static final String PROTOCOL_FILE_REQUEST = "FILE_REQUEST"; - private static final String PROTOCOL_FILE_DATA = "FILE_DATA"; - private static final String PROTOCOL_SYNC_COMPLETE = "SYNC_COMPLETE"; - private static final String PROTOCOL_ERROR = "ERROR"; - - private BluetoothAdapter bluetoothAdapter; - private TextView txtBluetoothStatus; - private TextView txtSyncProgress; - private Button btnMakeDiscoverable; - private Button btnScanDevices; - private Button btnCancelSync; - private ListView listPairedDevices; - private ListView listDiscoveredDevices; - - private ArrayAdapter pairedDevicesAdapter; - private ArrayAdapter discoveredDevicesAdapter; - private ArrayList pairedDevicesList; - private ArrayList discoveredDevicesList; - - private AcceptThread acceptThread; - private ConnectThread connectThread; - private ConnectedThread connectedThread; - private Handler mainHandler; - private File notesDirectory; - private boolean isScanning = false; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.bluetooth_sync_activity); - - // Enable up navigation - if (getActionBar() != null) { - getActionBar().setDisplayHomeAsUpEnabled(true); - getActionBar().setTitle("Bluetooth Sync"); - } - - mainHandler = new Handler(Looper.getMainLooper()); - initializeViews(); - setupNotesDirectory(); - initializeBluetooth(); - setupListeners(); - } - - private void initializeViews() { - txtBluetoothStatus = findViewById(R.id.txt_bluetooth_status); - txtSyncProgress = findViewById(R.id.txt_sync_progress); - btnMakeDiscoverable = findViewById(R.id.btn_make_discoverable); - btnScanDevices = findViewById(R.id.btn_scan_devices); - btnCancelSync = findViewById(R.id.btn_cancel_sync); - listPairedDevices = findViewById(R.id.list_paired_devices); - listDiscoveredDevices = findViewById(R.id.list_discovered_devices); - - // Initialize device lists - pairedDevicesList = new ArrayList<>(); - discoveredDevicesList = new ArrayList<>(); - - pairedDevicesAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1); - discoveredDevicesAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1); - - listPairedDevices.setAdapter(pairedDevicesAdapter); - listDiscoveredDevices.setAdapter(discoveredDevicesAdapter); - } - - private void setupNotesDirectory() { - String notesPath = getIntent().getStringExtra("notes_directory"); - if (notesPath != null) { - notesDirectory = new File(notesPath); - } else { - File externalFilesDir = getExternalFilesDir(null); - if (externalFilesDir != null) { - notesDirectory = new File(externalFilesDir, "notes"); - } else { - notesDirectory = new File(getFilesDir(), "notes"); - } - } - } - - private void initializeBluetooth() { - bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - - if (bluetoothAdapter == null) { - updateStatus("Bluetooth not supported on this device"); - disableAllButtons(); - return; - } - - if (!bluetoothAdapter.isEnabled()) { - updateStatus("Bluetooth is disabled"); - disableAllButtons(); - return; - } - - updateStatus("Bluetooth ready"); - loadPairedDevices(); - startAcceptThread(); - } - - private void setupListeners() { - btnMakeDiscoverable.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - makeDiscoverable(); - } - }); - - btnScanDevices.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (isScanning) { - stopDeviceDiscovery(); - } else { - startDeviceDiscovery(); - } - } - }); - - btnCancelSync.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - finish(); - } - }); - - listPairedDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - BluetoothDevice device = pairedDevicesList.get(position); - connectToDevice(device); - } - }); - - listDiscoveredDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - BluetoothDevice device = discoveredDevicesList.get(position); - connectToDevice(device); - } - }); - - // Register for broadcasts when a device is discovered - IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); - filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); - registerReceiver(discoveryReceiver, filter); - } - - private void loadPairedDevices() { - pairedDevicesList.clear(); - pairedDevicesAdapter.clear(); - - if (checkBluetoothPermission()) { - Set pairedDevices = bluetoothAdapter.getBondedDevices(); - if (pairedDevices.size() > 0) { - for (BluetoothDevice device : pairedDevices) { - pairedDevicesList.add(device); - String deviceInfo = device.getName() + "\n" + device.getAddress(); - pairedDevicesAdapter.add(deviceInfo); - } - } else { - pairedDevicesAdapter.add("No paired devices found"); - } - } else { - pairedDevicesAdapter.add("Bluetooth permission required"); - } - - pairedDevicesAdapter.notifyDataSetChanged(); - } - - private void makeDiscoverable() { - if (!checkBluetoothPermission()) { - Toast.makeText(this, "Bluetooth permission required", Toast.LENGTH_SHORT).show(); - return; - } - - Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); - discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, DISCOVERABLE_DURATION); - startActivityForResult(discoverableIntent, REQUEST_DISCOVERABLE); - } - - private void startDeviceDiscovery() { - if (!checkBluetoothPermission()) { - Toast.makeText(this, "Bluetooth permission required", Toast.LENGTH_SHORT).show(); - return; - } - - discoveredDevicesList.clear(); - discoveredDevicesAdapter.clear(); - discoveredDevicesAdapter.notifyDataSetChanged(); - - if (bluetoothAdapter.isDiscovering()) { - bluetoothAdapter.cancelDiscovery(); - } - - boolean started = bluetoothAdapter.startDiscovery(); - if (started) { - isScanning = true; - btnScanDevices.setText("Stop Scan"); - updateProgress("Scanning for devices..."); - } else { - Toast.makeText(this, "Failed to start device discovery", Toast.LENGTH_SHORT).show(); - } - } - - private void stopDeviceDiscovery() { - if (checkBluetoothPermission() && bluetoothAdapter.isDiscovering()) { - bluetoothAdapter.cancelDiscovery(); - } - isScanning = false; - btnScanDevices.setText("Scan for Devices"); - updateProgress(""); - } - - private void connectToDevice(final BluetoothDevice device) { - if (!checkBluetoothPermission()) { - Toast.makeText(this, "Bluetooth permission required", Toast.LENGTH_SHORT).show(); - return; - } - - // Stop discovery to save resources - if (bluetoothAdapter.isDiscovering()) { - bluetoothAdapter.cancelDiscovery(); - isScanning = false; - btnScanDevices.setText("Scan for Devices"); - } - - new AlertDialog.Builder(this) - .setTitle("Connect to Device") - .setMessage("Connect to " + device.getName() + " (" + device.getAddress() + ") for sync?") - .setPositiveButton("Connect", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - startConnectThread(device); - } - }) - .setNegativeButton("Cancel", null) - .show(); - } - - private void startConnectThread(BluetoothDevice device) { - // Cancel any existing connection attempts - if (connectThread != null) { - connectThread.cancel(); - connectThread = null; - } - - connectThread = new ConnectThread(device); - connectThread.start(); - updateProgress("Connecting to " + device.getName() + "..."); - } - - private void startAcceptThread() { - if (acceptThread != null) { - acceptThread.cancel(); - } - acceptThread = new AcceptThread(); - acceptThread.start(); - } - - private boolean checkBluetoothPermission() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - return checkSelfPermission(Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED; - } - return true; - } - - private void updateStatus(String status) { - mainHandler.post(new Runnable() { - @Override - public void run() { - txtBluetoothStatus.setText(status); - } - }); - Log.d(TAG, "Status: " + status); - } - - private void updateProgress(String progress) { - mainHandler.post(new Runnable() { - @Override - public void run() { - txtSyncProgress.setText(progress); - } - }); - Log.d(TAG, "Progress: " + progress); - } - - private void disableAllButtons() { - btnMakeDiscoverable.setEnabled(false); - btnScanDevices.setEnabled(false); - } - - // BroadcastReceiver for Bluetooth device discovery - private final BroadcastReceiver discoveryReceiver = new BroadcastReceiver() { - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - - if (BluetoothDevice.ACTION_FOUND.equals(action)) { - BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - if (device != null && checkBluetoothPermission()) { - String deviceName = device.getName(); - if (deviceName == null) { - deviceName = "Unknown Device"; - } - - // Avoid duplicates - boolean alreadyAdded = false; - for (BluetoothDevice existingDevice : discoveredDevicesList) { - if (existingDevice.getAddress().equals(device.getAddress())) { - alreadyAdded = true; - break; - } - } - - if (!alreadyAdded) { - discoveredDevicesList.add(device); - String deviceInfo = deviceName + "\n" + device.getAddress(); - discoveredDevicesAdapter.add(deviceInfo); - discoveredDevicesAdapter.notifyDataSetChanged(); - } - } - } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { - isScanning = false; - btnScanDevices.setText("Scan for Devices"); - updateProgress("Discovery finished. Found " + discoveredDevicesList.size() + " devices."); - } - } - }; - - // Thread for accepting incoming connections - private class AcceptThread extends Thread { - private BluetoothServerSocket serverSocket; - - public AcceptThread() { - try { - if (checkBluetoothPermission()) { - serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord( - SERVICE_NAME, SERVICE_UUID); - } - } catch (IOException e) { - Log.e(TAG, "Socket listen() failed", e); - } - } - - @Override - public void run() { - BluetoothSocket socket = null; - - while (true) { - try { - socket = serverSocket.accept(); - } catch (IOException e) { - Log.e(TAG, "Socket accept() failed", e); - break; - } - - if (socket != null) { - // Connection accepted - manageConnectedSocket(socket); - try { - serverSocket.close(); - } catch (IOException e) { - Log.e(TAG, "Could not close server socket", e); - } - break; - } - } - } - - public void cancel() { - try { - if (serverSocket != null) { - serverSocket.close(); - } - } catch (IOException e) { - Log.e(TAG, "Could not close server socket", e); - } - } - } - - // Thread for connecting to a device - private class ConnectThread extends Thread { - private BluetoothSocket socket; - private BluetoothDevice device; - - public ConnectThread(BluetoothDevice device) { - this.device = device; - - try { - if (checkBluetoothPermission()) { - socket = device.createRfcommSocketToServiceRecord(SERVICE_UUID); - } - } catch (IOException e) { - Log.e(TAG, "Socket create() failed", e); - } - } - - @Override - public void run() { - // Cancel discovery to save resources - if (checkBluetoothPermission() && bluetoothAdapter.isDiscovering()) { - bluetoothAdapter.cancelDiscovery(); - } - - try { - if (checkBluetoothPermission()) { - socket.connect(); - } - } catch (IOException e) { - Log.e(TAG, "Could not connect to device", e); - mainHandler.post(new Runnable() { - @Override - public void run() { - updateProgress("Connection failed: " + e.getMessage()); - Toast.makeText(BluetoothSyncActivity.this, "Connection failed", Toast.LENGTH_SHORT).show(); - } - }); - - try { - socket.close(); - } catch (IOException closeException) { - Log.e(TAG, "Could not close client socket", closeException); - } - return; - } - - // Connection successful - manageConnectedSocket(socket); - } - - public void cancel() { - try { - if (socket != null) { - socket.close(); - } - } catch (IOException e) { - Log.e(TAG, "Could not close client socket", e); - } - } - } - - // Thread for managing a connected socket - private class ConnectedThread extends Thread { - private BluetoothSocket socket; - private InputStream inputStream; - private OutputStream outputStream; - - public ConnectedThread(BluetoothSocket socket) { - this.socket = socket; - - try { - inputStream = socket.getInputStream(); - outputStream = socket.getOutputStream(); - } catch (IOException e) { - Log.e(TAG, "Error occurred when creating input/output streams", e); - } - } - - @Override - public void run() { - byte[] buffer = new byte[1024]; - int numBytes; - - // Keep listening to the InputStream while connected - while (true) { - try { - numBytes = inputStream.read(buffer); - String receivedMessage = new String(buffer, 0, numBytes, "UTF-8"); - handleReceivedMessage(receivedMessage); - } catch (IOException e) { - Log.d(TAG, "Input stream was disconnected", e); - mainHandler.post(new Runnable() { - @Override - public void run() { - updateProgress("Connection lost"); - } - }); - break; - } - } - } - - public void write(String message) { - try { - byte[] bytes = message.getBytes("UTF-8"); - outputStream.write(bytes); - Log.d(TAG, "Sent: " + message); - } catch (IOException e) { - Log.e(TAG, "Error occurred when sending data", e); - } - } - - public void cancel() { - try { - socket.close(); - } catch (IOException e) { - Log.e(TAG, "Could not close connected socket", e); - } - } - } - - private void manageConnectedSocket(BluetoothSocket socket) { - mainHandler.post(new Runnable() { - @Override - public void run() { - updateProgress("Connected! Starting sync..."); - } - }); - - // Cancel existing threads - if (connectThread != null) { - connectThread.cancel(); - connectThread = null; - } - if (acceptThread != null) { - acceptThread.cancel(); - acceptThread = null; - } - - // Start the connected thread - connectedThread = new ConnectedThread(socket); - connectedThread.start(); - - // Start the sync protocol - startSyncProtocol(); - } - - private void handleReceivedMessage(String message) { - Log.d(TAG, "Received: " + message); - - String[] parts = message.split("\\|", 2); - String command = parts[0]; - String data = parts.length > 1 ? parts[1] : ""; - - switch (command) { - case PROTOCOL_HANDSHAKE: - handleHandshake(data); - break; - case PROTOCOL_FILE_LIST: - handleFileList(data); - break; - case PROTOCOL_FILE_REQUEST: - handleFileRequest(data); - break; - case PROTOCOL_FILE_DATA: - handleFileData(data); - break; - case PROTOCOL_SYNC_COMPLETE: - handleSyncComplete(); - break; - case PROTOCOL_ERROR: - handleError(data); - break; - } - } - - private void startSyncProtocol() { - if (connectedThread != null) { - connectedThread.write(PROTOCOL_HANDSHAKE + "|" + android.os.Build.MODEL); - } - } - - private void handleHandshake(String deviceInfo) { - mainHandler.post(new Runnable() { - @Override - public void run() { - updateProgress("Handshake received from " + deviceInfo); - } - }); - - // Send our file list - sendFileList(); - } - - private void sendFileList() { - List notes = NoteManager.getAllNoteInfo(notesDirectory); - StringBuilder fileList = new StringBuilder(); - - for (NoteManager.NoteInfo note : notes) { - if (fileList.length() > 0) { - fileList.append(";"); - } - fileList.append(note.name).append(",") - .append(note.lastModified).append(",") - .append(note.hash); - } - - if (connectedThread != null) { - connectedThread.write(PROTOCOL_FILE_LIST + "|" + fileList.toString()); - } - } - - private void handleFileList(String fileListData) { - // Parse remote file list and determine what files to sync - mainHandler.post(new Runnable() { - @Override - public void run() { - updateProgress("Comparing files..."); - } - }); - - // Simple implementation: request all files that are different - // In a full implementation, you'd compare timestamps and hashes - String[] files = fileListData.split(";"); - for (String fileInfo : files) { - if (!fileInfo.isEmpty()) { - String[] parts = fileInfo.split(","); - if (parts.length >= 3) { - String fileName = parts[0]; - long timestamp = Long.parseLong(parts[1]); - String hash = parts[2]; - - // Check if we need this file - NoteManager.NoteInfo localNote = NoteManager.getNoteInfo(notesDirectory, fileName); - if (localNote == null || localNote.lastModified < timestamp || !localNote.hash.equals(hash)) { - // Request this file - if (connectedThread != null) { - connectedThread.write(PROTOCOL_FILE_REQUEST + "|" + fileName); - } - } - } - } - } - - // Send sync complete when done - mainHandler.postDelayed(new Runnable() { - @Override - public void run() { - if (connectedThread != null) { - connectedThread.write(PROTOCOL_SYNC_COMPLETE + "|"); - } - } - }, 1000); - } - - private void handleFileRequest(String fileName) { - String content = NoteManager.loadNote(notesDirectory, fileName); - if (content != null) { - if (connectedThread != null) { - connectedThread.write(PROTOCOL_FILE_DATA + "|" + fileName + ":" + content); - } - } else { - if (connectedThread != null) { - connectedThread.write(PROTOCOL_ERROR + "|File not found: " + fileName); - } - } - } - - private void handleFileData(String fileData) { - int colonIndex = fileData.indexOf(':'); - if (colonIndex > 0) { - String fileName = fileData.substring(0, colonIndex); - String content = fileData.substring(colonIndex + 1); - - boolean saved = NoteManager.saveNote(notesDirectory, fileName, content); - - mainHandler.post(new Runnable() { - @Override - public void run() { - if (saved) { - updateProgress("Received file: " + fileName); - } else { - updateProgress("Failed to save: " + fileName); - } - } - }); - } - } - - private void handleSyncComplete() { - mainHandler.post(new Runnable() { - @Override - public void run() { - updateProgress("Sync completed successfully!"); - Toast.makeText(BluetoothSyncActivity.this, "Sync completed!", Toast.LENGTH_LONG).show(); - - // Close connection after a delay - mainHandler.postDelayed(new Runnable() { - @Override - public void run() { - finish(); - } - }, 2000); - } - }); - } - - private void handleError(String error) { - mainHandler.post(new Runnable() { - @Override - public void run() { - updateProgress("Error: " + error); - Toast.makeText(BluetoothSyncActivity.this, "Sync error: " + error, Toast.LENGTH_SHORT).show(); - } - }); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - - if (requestCode == REQUEST_DISCOVERABLE) { - if (resultCode > 0) { - updateStatus("Device is discoverable for " + resultCode + " seconds"); - updateProgress("Waiting for incoming connections..."); - } else { - updateStatus("Discoverable request denied"); - } - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - default: - return super.onOptionsItemSelected(item); - } - } - - @Override - protected void onDestroy() { - super.onDestroy(); - - // Clean up threads - if (connectThread != null) { - connectThread.cancel(); - } - if (connectedThread != null) { - connectedThread.cancel(); - } - if (acceptThread != null) { - acceptThread.cancel(); - } - - // Unregister broadcast receiver - try { - unregisterReceiver(discoveryReceiver); - } catch (IllegalArgumentException e) { - // Receiver was not registered - } - - // Stop discovery - if (bluetoothAdapter != null && checkBluetoothPermission() && bluetoothAdapter.isDiscovering()) { - bluetoothAdapter.cancelDiscovery(); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/eu/octt/notetand/CustomActivity.java b/app/src/main/java/org/eu/octt/notetand/CustomActivity.java index cd17b74..d7703d3 100644 --- a/app/src/main/java/org/eu/octt/notetand/CustomActivity.java +++ b/app/src/main/java/org/eu/octt/notetand/CustomActivity.java @@ -1,7 +1,6 @@ package org.eu.octt.notetand; import android.annotation.SuppressLint; -import android.annotation.TargetApi; import android.app.Activity; import android.os.Build; import android.os.Bundle; diff --git a/app/src/main/java/org/eu/octt/notetand/MainActivity.java b/app/src/main/java/org/eu/octt/notetand/MainActivity.java index c60c8bb..c989092 100644 --- a/app/src/main/java/org/eu/octt/notetand/MainActivity.java +++ b/app/src/main/java/org/eu/octt/notetand/MainActivity.java @@ -22,33 +22,14 @@ public class MainActivity extends CustomActivity { NoteManager.setup(this); listNotes = findViewById(R.id.list_notes); -// var notesList = NoteManager.getAllNoteNames(); // new ArrayList(); -// var notesAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, notesList); -// listNotes.setAdapter(notesAdapter); - -// // Use Android/data/packagename/files/notes structure -// var notesDirectory = new File(getExternalFilesDir(null), "notes"); -// if (!notesDirectory.exists()) { -// notesDirectory.mkdirs(); -// } - - // for (var file : notesDirectory.listFiles()) { -// for (var file : NoteManager.notesDirectory.listFiles()) { -// if (file.isFile() && file.getName().toLowerCase().endsWith(".txt")) { -// notesList.add(file.getName()); -// } -// } - // notesAdapter.notifyDataSetChanged(); - - listNotes.setOnItemClickListener((parent, view, position, id) -> - launchNote(notesList.get(position), false)); + listNotes.setOnItemClickListener((parent, view, position, id) -> launchNote(notesList.get(position), false)); } @Override protected void onStart() { super.onStart(); - notesList = NoteManager.getAllNoteNames(); // new ArrayList(); + notesList = NoteManager.getAllNoteNames(); var notesAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, notesList); listNotes.setAdapter(notesAdapter); notesAdapter.notifyDataSetChanged(); diff --git a/app/src/main/java/org/eu/octt/notetand/MainActivity1.java b/app/src/main/java/org/eu/octt/notetand/MainActivity1.java deleted file mode 100644 index 47e8037..0000000 --- a/app/src/main/java/org/eu/octt/notetand/MainActivity1.java +++ /dev/null @@ -1,380 +0,0 @@ -package org.eu.octt.notetand; - -import android.Manifest; -import android.app.Activity; -import android.app.AlertDialog; -import android.bluetooth.BluetoothAdapter; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.os.Build; -import android.os.Bundle; -import android.view.ContextMenu; -import android.view.MenuItem; -import android.view.View; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.ListView; -import android.widget.TextView; -import android.widget.Toast; - -import java.io.File; -import java.util.ArrayList; - -public class MainActivity1 extends Activity { - - private static final int REQUEST_ENABLE_BT = 1001; - private static final int REQUEST_PERMISSIONS = 1002; - private static final int REQUEST_BLUETOOTH_PERMISSIONS = 1003; - - private ListView listNotes; - private TextView txtStatus; - private TextView txtNoteCount; - private Button btnSync; - private Button btnAddNote; - - private ArrayList notesList; - private ArrayAdapter notesAdapter; - private File notesDirectory; - private BluetoothAdapter bluetoothAdapter; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.main_activity_1); - - initializeViews(); - setupNotesDirectory(); - checkPermissions(); - initializeBluetooth(); - loadNotes(); - setupListeners(); - } - - private void initializeViews() { - listNotes = findViewById(R.id.list_notes); - txtStatus = findViewById(R.id.txt_status); - txtNoteCount = findViewById(R.id.txt_note_count); - btnSync = findViewById(R.id.btn_sync); - btnAddNote = findViewById(R.id.btn_add_note); - - notesList = new ArrayList<>(); - notesAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, notesList); - listNotes.setAdapter(notesAdapter); - - // Register context menu for long press - registerForContextMenu(listNotes); - } - - private void setupNotesDirectory() { - // Use Android/data/packagename/files/notes structure - File externalFilesDir = getExternalFilesDir(null); - if (externalFilesDir != null) { - notesDirectory = new File(externalFilesDir, "notes"); - if (!notesDirectory.exists()) { - boolean created = notesDirectory.mkdirs(); - if (created) { - updateStatus("Notes directory created"); - } else { - updateStatus("Failed to create notes directory"); - } - } - } else { - // Fallback to internal storage - notesDirectory = new File(getFilesDir(), "notes"); - if (!notesDirectory.exists()) { - notesDirectory.mkdirs(); - } - updateStatus("Using internal storage"); - } - } - - private void checkPermissions() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - ArrayList permissionsNeeded = new ArrayList<>(); - - // Storage permissions (for API < 30) - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { - if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) - != PackageManager.PERMISSION_GRANTED) { - permissionsNeeded.add(Manifest.permission.READ_EXTERNAL_STORAGE); - } - if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) - != PackageManager.PERMISSION_GRANTED) { - permissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); - } - } - - // Location permission for Bluetooth scanning - if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) - != PackageManager.PERMISSION_GRANTED) { - permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION); - } - - if (!permissionsNeeded.isEmpty()) { - requestPermissions(permissionsNeeded.toArray(new String[0]), REQUEST_PERMISSIONS); - } - } - } - - private void initializeBluetooth() { - bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - - if (bluetoothAdapter == null) { - updateStatus("Bluetooth not supported"); - btnSync.setEnabled(false); - return; - } - - if (!bluetoothAdapter.isEnabled()) { - updateStatus("Bluetooth disabled"); - btnSync.setText("Enable BT"); - } else { - updateStatus("Bluetooth ready"); - btnSync.setText("Sync"); - } - } - - private void loadNotes() { - notesList.clear(); - - if (notesDirectory != null && notesDirectory.exists()) { - File[] files = notesDirectory.listFiles(); - if (files != null) { - for (File file : files) { - if (file.isFile() && file.getName().endsWith(".txt")) { - String noteName = file.getName().replace(".txt", ""); - notesList.add(noteName); - } - } - } - } - - notesAdapter.notifyDataSetChanged(); - updateNoteCount(); - - if (notesList.isEmpty()) { - updateStatus("No notes found. Tap + to create one."); - } else { - updateStatus("Loaded " + notesList.size() + " notes"); - } - } - - private void setupListeners() { - btnAddNote.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - createNewNote(); - } - }); - - btnSync.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - handleSyncButtonClick(); - } - }); - - listNotes.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - String noteName = notesList.get(position); - openNote(noteName); - } - }); - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { - super.onCreateContextMenu(menu, v, menuInfo); - if (v.getId() == R.id.list_notes) { - AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; - String noteName = notesList.get(info.position); - menu.setHeaderTitle(noteName); - menu.add(0, 1, 0, "Open"); - menu.add(0, 2, 0, "Delete"); - } - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); - final String noteName = notesList.get(info.position); - - switch (item.getItemId()) { - case 1: // Open - openNote(noteName); - return true; - case 2: // Delete - new AlertDialog.Builder(this) - .setTitle("Delete Note") - .setMessage("Are you sure you want to delete '" + noteName + "'?") - .setPositiveButton("Delete", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - deleteNote(noteName); - } - }) - .setNegativeButton("Cancel", null) - .show(); - return true; - default: - return super.onContextItemSelected(item); - } - } - - private void createNewNote() { - // For now, create a simple numbered note - String newNoteName = "Note_" + System.currentTimeMillis(); - Intent intent = new Intent(this, NoteActivity.class); - intent.putExtra("note_name", newNoteName); - intent.putExtra("is_new", true); - startActivity(intent); - } - - private void openNote(String noteName) { - Intent intent = new Intent(this, NoteActivity.class); - intent.putExtra("note_name", noteName); - intent.putExtra("is_new", false); - startActivity(intent); - } - - private void deleteNote(String noteName) { - File noteFile = new File(notesDirectory, noteName + ".txt"); - if (noteFile.exists()) { - boolean deleted = noteFile.delete(); - if (deleted) { - updateStatus("Note deleted: " + noteName); - loadNotes(); - } else { - updateStatus("Failed to delete note"); - } - } - } - - private void handleSyncButtonClick() { - if (bluetoothAdapter == null) { - Toast.makeText(this, "Bluetooth not supported", Toast.LENGTH_SHORT).show(); - return; - } - - if (!bluetoothAdapter.isEnabled()) { - // Request to enable Bluetooth - Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); - startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); - } else { - // Check Bluetooth permissions for newer Android versions - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - checkBluetoothPermissions(); - } else { - startBluetoothSync(); - } - } - } - - private void checkBluetoothPermissions() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - ArrayList permissionsNeeded = new ArrayList<>(); - - if (checkSelfPermission(Manifest.permission.BLUETOOTH_SCAN) - != PackageManager.PERMISSION_GRANTED) { - permissionsNeeded.add(Manifest.permission.BLUETOOTH_SCAN); - } - if (checkSelfPermission(Manifest.permission.BLUETOOTH_CONNECT) - != PackageManager.PERMISSION_GRANTED) { - permissionsNeeded.add(Manifest.permission.BLUETOOTH_CONNECT); - } - if (checkSelfPermission(Manifest.permission.BLUETOOTH_ADVERTISE) - != PackageManager.PERMISSION_GRANTED) { - permissionsNeeded.add(Manifest.permission.BLUETOOTH_ADVERTISE); - } - - if (!permissionsNeeded.isEmpty()) { - requestPermissions(permissionsNeeded.toArray(new String[0]), - REQUEST_BLUETOOTH_PERMISSIONS); - } else { - startBluetoothSync(); - } - } else { - startBluetoothSync(); - } - } - - private void startBluetoothSync() { - Intent intent = new Intent(this, BluetoothSyncActivity.class); - intent.putExtra("notes_directory", notesDirectory.getAbsolutePath()); - startActivity(intent); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - - if (requestCode == REQUEST_ENABLE_BT) { - if (resultCode == RESULT_OK) { - updateStatus("Bluetooth enabled"); - btnSync.setText("Sync"); - } else { - updateStatus("Bluetooth enable cancelled"); - } - } - } - - @Override - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - - switch (requestCode) { - case REQUEST_PERMISSIONS: - boolean allGranted = true; - for (int result : grantResults) { - if (result != PackageManager.PERMISSION_GRANTED) { - allGranted = false; - break; - } - } - if (allGranted) { - updateStatus("Permissions granted"); - } else { - updateStatus("Some permissions denied"); - } - break; - - case REQUEST_BLUETOOTH_PERMISSIONS: - boolean bluetoothGranted = true; - for (int result : grantResults) { - if (result != PackageManager.PERMISSION_GRANTED) { - bluetoothGranted = false; - break; - } - } - if (bluetoothGranted) { - startBluetoothSync(); - } else { - Toast.makeText(this, "Bluetooth permissions required for sync", - Toast.LENGTH_SHORT).show(); - } - break; - } - } - - @Override - protected void onResume() { - super.onResume(); - loadNotes(); // Refresh notes list when returning from editor - } - - private void updateStatus(String status) { - txtStatus.setText(status); - } - - private void updateNoteCount() { - int count = notesList.size(); - txtNoteCount.setText(count + (count == 1 ? " note" : " notes")); - } - - public File getNotesDirectory() { - return notesDirectory; - } -} \ No newline at end of file diff --git a/app/src/main/java/org/eu/octt/notetand/NoteActivity.java b/app/src/main/java/org/eu/octt/notetand/NoteActivity.java index e9ce0d2..d6c0c83 100644 --- a/app/src/main/java/org/eu/octt/notetand/NoteActivity.java +++ b/app/src/main/java/org/eu/octt/notetand/NoteActivity.java @@ -1,11 +1,13 @@ package org.eu.octt.notetand; +import android.annotation.SuppressLint; import android.app.AlertDialog; -import android.content.DialogInterface; import android.content.Intent; +import android.graphics.Typeface; import android.os.Build; import android.os.Bundle; import android.text.Editable; +import android.text.InputType; import android.text.TextWatcher; import android.view.KeyEvent; import android.view.Menu; @@ -17,7 +19,6 @@ import android.widget.Toast; import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.Locale; import java.util.Random; public class NoteActivity extends CustomActivity { @@ -26,8 +27,6 @@ public class NoteActivity extends CustomActivity { private EditText editNoteName; private EditText editNoteContent; private TextView txtNoteInfo; -// private Button btnSave; -// private Button btnDelete; private String originalNoteName; private String originalContent; @@ -54,8 +53,45 @@ public class NoteActivity extends CustomActivity { editNoteName = findViewById(R.id.edit_note_name); editNoteContent = findViewById(R.id.edit_note_content); txtNoteInfo = findViewById(R.id.txt_note_info); -// btnSave = findViewById(R.id.btn_save); -// btnDelete = findViewById(R.id.btn_delete); + + var fontSize = SettingsManager.getFontSize(); + if (fontSize > 0) + editNoteContent.setTextSize(fontSize); + + Integer flag = null; + var contentFlags = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE; + switch (SettingsManager.getKeyboardMode()) { + case "normal": + editNoteContent.setInputType(contentFlags); + break; + case "no_suggestions": + flag = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; + break; + case "privacy": + flag = InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD; + break; + } + if (flag != null) { + editNoteContent.setInputType(contentFlags | flag); + editNoteName.setInputType(InputType.TYPE_CLASS_TEXT | flag); + } + + Typeface typeface = null; + switch (SettingsManager.getFontType()) { + case "sans_serif": + typeface = Typeface.SANS_SERIF; + break; + case "serif": + typeface = Typeface.SERIF; + break; + case "monospace": + typeface = Typeface.MONOSPACE; + break; + } + if (typeface != null) { + editNoteContent.setTypeface(typeface); + editNoteName.setTypeface(typeface); + } } private void setupNotesDirectory() { @@ -68,6 +104,7 @@ public class NoteActivity extends CustomActivity { } } + @SuppressLint("SimpleDateFormat") private void loadNoteFromIntent() { Intent intent = getIntent(); @@ -80,7 +117,6 @@ public class NoteActivity extends CustomActivity { } if (originalNoteName == null) { - // originalNoteName = "Note_" + System.currentTimeMillis() + ".txt"; originalNoteName = (new SimpleDateFormat("yyyy-MM-dd HH-mm-ss.SSS")).format(new Date()) + ' ' + EMOJIS[(new Random()).nextInt(EMOJIS.length)] + ".txt"; isNewNote = true; } @@ -98,13 +134,7 @@ public class NoteActivity extends CustomActivity { originalContent = ""; Toast.makeText(this, "Error loading note", Toast.LENGTH_SHORT).show(); } - // btnDelete.setVisibility(View.VISIBLE); - //} else if (originalNoteName == null && originalContent == null) { - // originalContent = intent.getStringExtra("content"); - } // else { - // originalContent = ""; - // // btnDelete.setVisibility(View.GONE); - // } + } if (originalContent == null) { originalContent = ""; @@ -116,10 +146,6 @@ public class NoteActivity extends CustomActivity { } private void setupListeners() { -// btnSave.setOnClickListener(v -> saveNote()); -// -// btnDelete.setOnClickListener(v -> confirmDeleteNote()); - // Track changes to note name editNoteName.addTextChangedListener(new TextWatcher() { @Override @@ -157,13 +183,7 @@ public class NoteActivity extends CustomActivity { hasUnsavedChanges = !currentName.equals(originalNoteName) || !currentContent.equals(originalContent); // Update title to indicate unsaved changes - //if (getActionBar() != null) { - if (hasUnsavedChanges) { - /*getActionBar().*/setTitle("* " + getString(R.string.note) /* currentName */); - } else { - /*getActionBar().*/setTitle(getString(R.string.note) /* currentName */); - } - //} + setTitle((hasUnsavedChanges ? "* " : "") + getString(R.string.note)); } private void updateNoteInfo() { @@ -175,13 +195,12 @@ public class NoteActivity extends CustomActivity { if (isNewNote && !hasUnsavedChanges) { txtNoteInfo.setText(R.string.new_note); } else { - txtNoteInfo.setText(String.format(Locale.getDefault(), "%d chars, %d words, %d lines", characterCount, wordCount, lineCount)); + txtNoteInfo.setText(getString(R.string.note_info_bar, characterCount, wordCount, lineCount)); } } private void saveNote() { String noteName = editNoteName.getText().toString().trim(); - // String content = editNoteContent.getText().toString(); // Validate note name if (noteName.isEmpty()) { @@ -228,12 +247,8 @@ public class NoteActivity extends CustomActivity { originalContent = content; isNewNote = false; hasUnsavedChanges = false; - // btnDelete.setVisibility(View.VISIBLE); - - //if (getActionBar() != null) { - /*getActionBar().*/setTitle(getString(R.string.note) /* noteName */); - //} + setTitle(getString(R.string.note)); Toast.makeText(this, R.string.note_saved, Toast.LENGTH_SHORT).show(); updateNoteInfo(); } else { @@ -291,17 +306,6 @@ public class NoteActivity extends CustomActivity { return true; } -// @Override -// public boolean onOptionsItemSelected(MenuItem item) { -// switch (item.getItemId()) { -// case android.R.id.home: -// onBackPressed(); -// return true; -// default: -// return super.onOptionsItemSelected(item); -// } -// } - @Override public void onBackPressed() { if (hasUnsavedChanges) { diff --git a/app/src/main/java/org/eu/octt/notetand/ReceiveActivity.java b/app/src/main/java/org/eu/octt/notetand/ReceiveActivity.java index 6732443..e00ccfa 100644 --- a/app/src/main/java/org/eu/octt/notetand/ReceiveActivity.java +++ b/app/src/main/java/org/eu/octt/notetand/ReceiveActivity.java @@ -1,8 +1,6 @@ package org.eu.octt.notetand; -import android.Manifest; import android.annotation.SuppressLint; -import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; @@ -14,7 +12,6 @@ import android.widget.Toast; import java.io.EOFException; import java.io.IOException; -import java.io.InputStream; import java.nio.ByteBuffer; public class ReceiveActivity extends CustomActivity { @@ -82,32 +79,15 @@ public class ReceiveActivity extends CustomActivity { writeStatus("Waiting for new client connection..."); socket = server.accept(); - // if (!socket.isConnected()) return; - var client = socket.getRemoteDevice(); - // textStatus.append("Connected to client!\n"); - // textStatus.append("Connected: " + client.getName() + " : " + client.getAddress() + '\n'); writeStatus("Connected: " + client.getName() + " : " + NoteTand.censorMac(client.getAddress())); - - // byte[] buffer = new byte[1024]; -// int bytes; -// -// while ((bytes = socket.getInputStream().read(buffer)) != -1) { -// var received = new String(buffer, 0, bytes); -// -// // runOnUiThread(() -> Toast.makeText(this, "Received: " + received, Toast.LENGTH_SHORT).show()); -// // textStatus.append(received + '\n'); -// writeStatus("Receiving data..."); -// writeStatus("> " + received); -// } - writeStatus("Reading data..."); - var titleLength = ByteBuffer.wrap(readFully(4)).getInt(); // ByteBuffer.wrap(intBuffer).order(ByteOrder.BIG_ENDIAN).getInt(); // or LITTLE_ENDIAN + var titleLength = ByteBuffer.wrap(readFully(4)).getInt(); var titleBytes = readFully(titleLength); var noteTitle = new String(titleBytes, "UTF-8"); - var bodyLength = ByteBuffer.wrap(readFully(4)).getInt(); // ByteBuffer.wrap(intBuffer).order(ByteOrder.BIG_ENDIAN).getInt(); + var bodyLength = ByteBuffer.wrap(readFully(4)).getInt(); var bodyBytes = readFully(bodyLength); var noteBody = new String(bodyBytes, "UTF-8"); @@ -117,8 +97,6 @@ public class ReceiveActivity extends CustomActivity { } else { writeStatus("Content length mismatch! Expected " + titleLength + " + " + bodyLength + ", got " + titleBytes.length + " + " + bodyBytes.length); } - - // writeStatus("Finished receiving!"); } } catch (IOException e) { if (!stopped) { @@ -150,7 +128,7 @@ public class ReceiveActivity extends CustomActivity { runOnUiThread(() -> textStatus.append(text + '\n')); } - byte[] readFully(/* InputStream in, byte[] buffer, */ int length) throws IOException { + byte[] readFully(int length) throws IOException { byte[] buffer = new byte[length]; int offset = 0; while (offset < length) { diff --git a/app/src/main/java/org/eu/octt/notetand/SendActivity.java b/app/src/main/java/org/eu/octt/notetand/SendActivity.java index 7381767..a63e155 100644 --- a/app/src/main/java/org/eu/octt/notetand/SendActivity.java +++ b/app/src/main/java/org/eu/octt/notetand/SendActivity.java @@ -1,7 +1,6 @@ package org.eu.octt.notetand; import android.annotation.SuppressLint; -import android.app.Activity; import android.app.AlertDialog; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -16,10 +15,7 @@ import android.widget.Toast; import java.io.IOException; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Objects; -import java.util.Set; public class SendActivity extends CustomActivity { BluetoothSocket socket; @@ -87,16 +83,13 @@ public class SendActivity extends CustomActivity { listPairedDevices.setOnItemClickListener((parent, view, position, id) -> { statusLog = ""; dialog = new AlertDialog.Builder(this) - .setTitle("Sending Note") + .setTitle(R.string.sending_note) .setMessage("Preparing...") // .setNegativeButton("Abort", null) - .setNeutralButton("Close", null) + .setNeutralButton(R.string.close, null) .show(); - //.create(); setDialogCancelable(false); - //dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setEnabled(false); - //dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setVisibility(ListView.GONE); - //dialog.show(); + var device = pairedDevicesList.get(position); new Thread(() -> { try { @@ -124,16 +117,13 @@ public class SendActivity extends CustomActivity { output.write(contentBytes); writeStatus("Note sent!"); - //dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setVisibility(ListView.VISIBLE); - //dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setEnabled(true); - //dialog.setCancelable(true); setDialogCancelable(true); socket.getInputStream().close(); socket.getOutputStream().close(); socket.close(); } catch (IOException e) { - // e.printStackTrace(); + e.printStackTrace(); Log.e("Bluetooth", "Connection failed", e); writeStatus(e.getMessage()); setDialogCancelable(true); @@ -162,7 +152,6 @@ public class SendActivity extends CustomActivity { void setDialogCancelable(boolean status) { runOnUiThread(() -> { - //dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setVisibility(ListView.VISIBLE); dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setEnabled(status); dialog.setCancelable(status); }); diff --git a/app/src/main/java/org/eu/octt/notetand/SettingsActivity.java b/app/src/main/java/org/eu/octt/notetand/SettingsActivity.java index 4704121..c845626 100644 --- a/app/src/main/java/org/eu/octt/notetand/SettingsActivity.java +++ b/app/src/main/java/org/eu/octt/notetand/SettingsActivity.java @@ -1,15 +1,18 @@ package org.eu.octt.notetand; -import android.app.Fragment; -import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; +import android.text.Editable; +import android.text.InputFilter; +import android.text.InputType; +import android.text.TextWatcher; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.BaseAdapter; import android.widget.CheckBox; +import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.Spinner; @@ -19,35 +22,29 @@ import java.util.ArrayList; import java.util.Arrays; public class SettingsActivity extends CustomActivity { -// @Override -// protected void onCreate(Bundle savedInstanceState) { -// super.onCreate(savedInstanceState); -// // getFragmentManager().beginTransaction().add(new SettingsFragment(), "").commit(); -// // addPreferencesFromResource(R.xml.preferences); -// -// } - -// class SettingsFragment extends Fragment { -// -// } - - private ListView listView; - private ArrayList settingViews = new ArrayList<>(); + private final ArrayList settingViews = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - listView = new ListView(this); + var listView = new ListView(this); - settingViews.add(createCheckboxSetting(getString(R.string.censor_mac), "censor_mac", true)); + // autosave + // default_location if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) - settingViews.add(createSpinnerSetting(getString(R.string.app_theme), "theme", new String[]{"system", "material_dark", "material_light", "holo_dark", "holo_light"}, "system")); + settingViews.add(createSpinnerSetting(getString(R.string.app_theme), "theme", SettingsManager.THEMES_FULL)); else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) - settingViews.add(createSpinnerSetting(getString(R.string.app_theme), "theme", new String[]{"system", "holo_dark", "holo_light"}, "system")); + settingViews.add(createSpinnerSetting(getString(R.string.app_theme), "theme", SettingsManager.THEMES_LEGACY)); - // settingViews.add(createNumberSetting(getString(R.string.font_size), "font_size")); + settingViews.add(createNumberSetting(getString(R.string.font_size), "font_size", 0, 1)); + + settingViews.add(createSpinnerSetting(getString(R.string.font_type), "font_type", SettingsManager.FONT_TYPES)); + + settingViews.add(createSpinnerSetting(getString(R.string.keyboard_mode), "keyboard_mode", SettingsManager.KEYBOARD_MODES)); + + settingViews.add(createCheckboxSetting(getString(R.string.censor_mac), "censor_mac", true)); // Adapter to wrap views into ListView listView.setAdapter(new BaseAdapter() { @@ -76,41 +73,79 @@ public class SettingsActivity extends CustomActivity { } private View createCheckboxSetting(String label, String key, boolean defaultValue) { - LinearLayout layout = new LinearLayout(this); - layout.setOrientation(LinearLayout.HORIZONTAL); - layout.setPadding(32, 32, 32, 32); + var layout = createLayout(LinearLayout.HORIZONTAL); - TextView textView = new TextView(this); + var textView = new TextView(this); textView.setText(label); - textView.setTextSize(16); + // textView.setTextSize(16); textView.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1)); - CheckBox checkBox = new CheckBox(this); + var checkBox = new CheckBox(this); checkBox.setChecked(SettingsManager.prefs.getBoolean(key, defaultValue)); - checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> { - SettingsManager.prefs.edit().putBoolean(key, isChecked).apply(); - }); + checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> SettingsManager.prefs.edit().putBoolean(key, isChecked).apply()); layout.addView(textView); layout.addView(checkBox); return layout; } - private View createSpinnerSetting(String label, String key, String[] options, String defaultValue) { - LinearLayout layout = new LinearLayout(this); - layout.setOrientation(LinearLayout.VERTICAL); - layout.setPadding(32, 32, 32, 32); + private View createNumberSetting(String label, String key, int defaultValue, int min) { + var layout = createLayout(LinearLayout.HORIZONTAL); - TextView textView = new TextView(this); + var textView = new TextView(this); textView.setText(label); - textView.setTextSize(16); + // textView.setTextSize(16); + textView.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1)); - Spinner spinner = new Spinner(this); + var editNumber = new EditText(this); + editNumber.setInputType(InputType.TYPE_CLASS_NUMBER); + editNumber.setFilters(new InputFilter[]{(source, start, end, dest, dstart, dend) -> { + try { + String input = dest.toString() + source.toString(); + int value = Integer.parseInt(input); + if (value >= min) { + return null; // Accept the input + } + } catch (NumberFormatException e) { + // Ignore invalid input + } + return ""; // Reject the input + }}); + var number = SettingsManager.prefs.getInt(key, defaultValue); + if (number >= min) + editNumber.setText(String.valueOf(number)); + editNumber.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) {} + + @Override + public void afterTextChanged(Editable s) { + var text = s.toString(); + SettingsManager.prefs.edit().putInt(key, !text.isEmpty() ? Integer.parseInt(text) : 0).apply(); + } + }); + + layout.addView(textView); + layout.addView(editNumber); + return layout; + } + + private View createSpinnerSetting(String label, String key, String[] options) { + var layout = createLayout(LinearLayout.VERTICAL); + + var textView = new TextView(this); + textView.setText(label); + // textView.setTextSize(16); + + var spinner = new Spinner(this); ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, options); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); - String currentValue = SettingsManager.prefs.getString(key, defaultValue); + var currentValue = SettingsManager.prefs.getString(key, options[0]); int selectedIndex = Arrays.asList(options).indexOf(currentValue); spinner.setSelection(Math.max(selectedIndex, 0)); @@ -125,4 +160,11 @@ public class SettingsActivity extends CustomActivity { layout.addView(spinner); return layout; } + + private LinearLayout createLayout(int orientation) { + var layout = new LinearLayout(this); + layout.setOrientation(orientation); + layout.setPadding(16, 16, 16, 16); + return layout; + } } diff --git a/app/src/main/java/org/eu/octt/notetand/SettingsManager.java b/app/src/main/java/org/eu/octt/notetand/SettingsManager.java index 9a05b3d..628a6e3 100644 --- a/app/src/main/java/org/eu/octt/notetand/SettingsManager.java +++ b/app/src/main/java/org/eu/octt/notetand/SettingsManager.java @@ -6,6 +6,11 @@ import android.content.Context; import android.content.SharedPreferences; public class SettingsManager { + static final String[] THEMES_FULL = {"system", "material_dark", "material_light", "holo_dark", "holo_light"}; + static final String[] THEMES_LEGACY = {"system", "holo_dark", "holo_light"}; + static final String[] FONT_TYPES = {"default", "sans_serif", "serif", "monospace"}; + static final String[] KEYBOARD_MODES = {"autocorrect", "normal", "no_suggestions", "privacy"}; + static SharedPreferences prefs; static void setup(Context context) { @@ -18,6 +23,18 @@ public class SettingsManager { } static String getTheme() { - return prefs.getString("theme", "system"); + return prefs.getString("theme", THEMES_FULL[0]); + } + + static int getFontSize() { + return prefs.getInt("font_size", 0); + } + + static String getFontType() { + return prefs.getString("font_type", FONT_TYPES[0]); + } + + static String getKeyboardMode() { + return prefs.getString("keyboard_mode", KEYBOARD_MODES[0]); } } diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index 2b068d1..0000000 --- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 07d5da9..0000000 --- a/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/activity_note.xml b/app/src/main/res/layout/activity_note.xml index 7f92392..20e608b 100644 --- a/app/src/main/res/layout/activity_note.xml +++ b/app/src/main/res/layout/activity_note.xml @@ -4,7 +4,6 @@ android:layout_height="match_parent" android:orientation="vertical"> - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_receive.xml b/app/src/main/res/layout/activity_receive.xml index 57c495f..644236f 100644 --- a/app/src/main/res/layout/activity_receive.xml +++ b/app/src/main/res/layout/activity_receive.xml @@ -8,6 +8,6 @@ android:id="@+id/text_status" android:layout_width="match_parent" android:layout_height="wrap_content" - android:fontFamily="monospace" /> + android:typeface="monospace" /> \ No newline at end of file diff --git a/app/src/main/res/layout/bluetooth_sync_activity.xml b/app/src/main/res/layout/bluetooth_sync_activity.xml deleted file mode 100644 index 666c683..0000000 --- a/app/src/main/res/layout/bluetooth_sync_activity.xml +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -