Skip to content

Commit 03dad5c

Browse files
committed
Fixes for a final release
1 parent 5712f41 commit 03dad5c

5 files changed

Lines changed: 55 additions & 55 deletions

File tree

android/app/src/main/java/io/github/nrontsis/noteoptimizer/MainActivity.java

Lines changed: 36 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
import android.content.ContentValues;
44
import android.content.Intent;
5+
import android.content.SharedPreferences;
56
import android.net.Uri;
67
import android.os.Bundle;
78
import android.os.Environment;
9+
import android.os.Handler;
10+
import android.os.Looper;
811
import android.provider.MediaStore;
912
import android.util.Base64;
1013
import android.util.Log;
@@ -13,7 +16,6 @@
1316

1417
import androidx.activity.OnBackPressedCallback;
1518
import androidx.appcompat.app.AppCompatActivity;
16-
import androidx.core.content.FileProvider;
1719
import androidx.core.content.IntentCompat;
1820

1921
import java.io.*;
@@ -22,80 +24,69 @@ public class MainActivity extends AppCompatActivity {
2224

2325
private static final String TAG = "NoteOptimizer";
2426
private static final String APP_URL = "https://nrontsis.github.io/boox-note-optimizer";
25-
private static final String PROVIDER = "io.github.nrontsis.noteoptimizer.fileprovider";
2627
private static final String BOOX_NOTES = "com.onyx.android.note";
28+
private static final String PREFS = "exports";
29+
private static final String PREF_LAST_URI = "last_export_uri";
2730

2831
private WebView webView;
32+
private final Handler handler = new Handler(Looper.getMainLooper());
2933

3034
private static final String EXPORT_FOLDER = Environment.DIRECTORY_DOWNLOADS + "/Note Optimizer";
3135

32-
/** Write file to Downloads/Note Optimizer via MediaStore. Cleans folder first. */
36+
/** Write file to Downloads/Note Optimizer via MediaStore. Deletes previous export first. */
3337
private Uri writeToDownloads(byte[] data, String fileName) throws IOException {
34-
// Clean all previous exports in our subfolder
35-
try {
36-
getContentResolver().delete(
37-
MediaStore.Downloads.EXTERNAL_CONTENT_URI,
38-
MediaStore.Downloads.RELATIVE_PATH + " IN (?,?)",
39-
new String[]{EXPORT_FOLDER + "/", EXPORT_FOLDER});
40-
} catch (Exception ignored) {}
38+
// Delete previous export by its exact URI
39+
SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
40+
String lastUri = prefs.getString(PREF_LAST_URI, null);
41+
if (lastUri != null) {
42+
try { getContentResolver().delete(Uri.parse(lastUri), null, null); }
43+
catch (Exception ignored) {}
44+
}
4145

4246
ContentValues cv = new ContentValues();
4347
cv.put(MediaStore.Downloads.DISPLAY_NAME, fileName);
4448
cv.put(MediaStore.Downloads.MIME_TYPE, "application/octet-stream");
4549
cv.put(MediaStore.Downloads.RELATIVE_PATH, EXPORT_FOLDER);
46-
cv.put(MediaStore.Downloads.IS_PENDING, 1);
4750
Uri uri = getContentResolver().insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, cv);
4851
if (uri == null) throw new IOException("Failed to create Downloads entry");
4952
try (OutputStream os = getContentResolver().openOutputStream(uri)) {
5053
if (os == null) throw new IOException("Failed to open output stream");
5154
os.write(data);
5255
}
53-
// Mark as complete so other apps can read it
54-
ContentValues done = new ContentValues();
55-
done.put(MediaStore.Downloads.IS_PENDING, 0);
56-
getContentResolver().update(uri, done, null, null);
56+
57+
prefs.edit().putString(PREF_LAST_URI, uri.toString()).apply();
5758
return uri;
5859
}
5960

60-
/** Try to open a file in Boox Notes via MediaStore URI, then chooser. */
61+
/** Open a file in Boox Notes, with a single retry to work around MediaStore lag. */
6162
private void openInBooxNotes(Uri uri) {
62-
String[] actions = {Intent.ACTION_VIEW, Intent.ACTION_SEND};
63-
String[] mimes = {"application/zip", "application/x-zip-compressed",
64-
"application/octet-stream", "*/*"};
65-
66-
for (String action : actions) {
67-
for (String mime : mimes) {
68-
Intent intent = new Intent(action);
69-
if (Intent.ACTION_VIEW.equals(action)) {
70-
intent.setDataAndType(uri, mime);
71-
} else {
72-
intent.setType(mime);
73-
intent.putExtra(Intent.EXTRA_STREAM, uri);
74-
}
75-
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
76-
intent.setPackage(BOOX_NOTES);
77-
try {
78-
startActivity(intent);
79-
return;
80-
} catch (Exception ignored) {}
81-
}
82-
}
63+
Intent intent = new Intent(Intent.ACTION_VIEW);
64+
intent.setDataAndType(uri, "*/*");
65+
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
66+
intent.setPackage(BOOX_NOTES);
8367

84-
// Fallback: chooser
85-
Intent fallback = new Intent(Intent.ACTION_VIEW);
86-
fallback.setDataAndType(uri, "application/octet-stream");
87-
fallback.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
88-
startActivity(Intent.createChooser(fallback, "Open with"));
68+
try {
69+
startActivity(intent);
70+
handler.postDelayed(() -> {
71+
try { startActivity(intent); }
72+
catch (Exception ignored) {}
73+
}, 1500);
74+
} catch (Exception e) {
75+
Intent fallback = new Intent(Intent.ACTION_VIEW);
76+
fallback.setDataAndType(uri, "*/*");
77+
fallback.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
78+
startActivity(Intent.createChooser(fallback, "Open with"));
79+
}
8980
}
9081

91-
/* ── JS bridge: receives base64 file data from the web page ── */
82+
/* ── JS bridge ── */
9283
private class AndroidBridge {
9384
@JavascriptInterface
9485
public void receiveFile(String base64, String fileName) {
9586
try {
9687
byte[] data = Base64.decode(base64, Base64.DEFAULT);
9788
Uri uri = writeToDownloads(data, fileName);
98-
openInBooxNotes(uri);
89+
runOnUiThread(() -> openInBooxNotes(uri));
9990
} catch (Exception e) {
10091
Log.e(TAG, "receiveFile failed", e);
10192
runOnUiThread(() ->
@@ -125,7 +116,6 @@ public void onPageFinished(WebView view, String url) {
125116
}
126117
});
127118

128-
/* ── Intercept blob: downloads → fetch via JS → pass to native ── */
129119
webView.setDownloadListener((url, userAgent, contentDisposition, mimetype, contentLength) -> {
130120
if (url.startsWith("blob:")) {
131121
String fetchJs =
@@ -149,7 +139,7 @@ public void onPageFinished(WebView view, String url) {
149139
webView.loadUrl(APP_URL);
150140
}
151141

152-
/* ── Inbound share: .note file → inject into web app cache ── */
142+
/* ── Inbound share ── */
153143
@Override
154144
protected void onNewIntent(Intent intent) {
155145
super.onNewIntent(intent);
@@ -162,7 +152,6 @@ private void handleInboundShare(Intent intent) {
162152
Uri uri = IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri.class);
163153
if (uri == null) return;
164154

165-
// Clear the intent so we don't re-process it on page reload
166155
setIntent(new Intent(Intent.ACTION_MAIN));
167156

168157
try {
@@ -177,7 +166,6 @@ private void handleInboundShare(Intent intent) {
177166
String base64 = Base64.encodeToString(baos.toByteArray(), Base64.NO_WRAP);
178167
String name = getFileName(uri);
179168

180-
// Stash file on window; web app picks it up once WASM is ready
181169
String js =
182170
"(function() {" +
183171
" const b64 = '" + base64 + "';" +
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
3+
<item android:drawable="@android:color/white" />
4+
<item
5+
android:width="320dp"
6+
android:height="320dp"
7+
android:gravity="center">
8+
<bitmap
9+
android:gravity="fill"
10+
android:src="@mipmap/ic_launcher" />
11+
</item>
12+
</layer-list>

android/build.sh

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ cd "$SCRIPT_DIR"
77
KEYSTORE="${1:-keystore.jks}"
88
KEYSTORE_PASSWORD="${KEYSTORE_PASSWORD:-noteoptimizer}"
99

10-
echo "==> Building Docker image..."
10+
echo "==> Building Docker image (layer cache)..."
1111
docker build -t note-optimizer-builder "$SCRIPT_DIR"
1212

1313
# ── Generate keystore if it doesn't exist (inside Docker so keytool isn't needed locally) ──
@@ -32,15 +32,16 @@ echo "==> Building Android APK..."
3232
docker run --rm \
3333
-v "$SCRIPT_DIR":/project \
3434
-v "$KEYSTORE_ABS":/keystore.jks:ro \
35+
-v note-optimizer-gradle-cache:/root/.gradle \
3536
-e KEYSTORE_PATH=/keystore.jks \
3637
-e KEYSTORE_PASSWORD="$KEYSTORE_PASSWORD" \
3738
note-optimizer-builder \
3839
bash -c "
3940
chmod +x gradlew 2>/dev/null || true
4041
if [ ! -f gradlew ]; then
41-
gradle wrapper --gradle-version 8.11.1 --no-daemon
42+
gradle wrapper --gradle-version 8.11.1
4243
fi
43-
./gradlew assembleRelease --no-daemon
44+
./gradlew assembleRelease
4445
cp app/build/outputs/apk/release/app-release.apk /project/NoteOptimizer.apk
4546
rm -rf app/build/outputs/apk
4647
"

web/index.html

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,13 +394,12 @@ <h3 class="font-bold text-gray-900 mb-1 uppercase text-xs tracking-wider">MIT Li
394394
let app = null;
395395
let filename = "document";
396396
function exportName() {
397-
// Strip existing __HH_mm_ss suffix and (N) copy suffixes, then append current time
397+
// Strip existing __HH_MM suffix and (N) copy suffixes, then append current time
398398
const base = filename.replace(/\(\d+\)$/, '').replace(/__\d{2}_\d{2}(_\d{2})?$/, '').trimEnd();
399399
const now = new Date();
400400
const hh = String(now.getHours()).padStart(2, '0');
401401
const mm = String(now.getMinutes()).padStart(2, '0');
402-
const ss = String(now.getSeconds()).padStart(2, '0');
403-
return `${base}__${hh}_${mm}_${ss}.note`;
402+
return `${base}__${hh}_${mm}.note`;
404403
}
405404
let page = 0;
406405
let originalFileSize = 0;

web/sw.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const CACHE_NAME = 'boox-optimizer-v38';
1+
const CACHE_NAME = 'boox-optimizer-v39';
22

33
const APP_SHELL = [
44
'./',

0 commit comments

Comments
 (0)