Skip to content

Commit 970fc2a

Browse files
committed
feat(result): re-edit loop — go back to Layout (or any earlier step) after processing and re-process with new settings
- Result step gets a 'Change layout & re-process' button (setStep 3) - Stepper: completed steps now clickable from the result step too - process() revokes the previous blob URL so repeated edits don't leak memory - i18n: rs.tweak in all 7 languages - release: v2.4.0
1 parent 5a851d7 commit 970fc2a

7 files changed

Lines changed: 33 additions & 12 deletions

File tree

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "notes-printifier",
3-
"version": "2.3.0",
3+
"version": "2.4.0",
44
"private": true,
55
"description": "Turn lecture PDFs into paper- and ink-saving print-ready PDFs — 100% client-side, bilingual (EN/हिन्दी), installable as a PWA and an offline Android app.",
66
"license": "MIT",

‎public/version.json‎

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
{
2-
"version": "2.3.0",
2+
"version": "2.4.0",
33
"updated": "2026-11-01",
44
"notes": [
5-
"Fixed — IMPORTANT: light-blue pen strokes no longer vanish when ink-saving is on. Pale blue handwriting and highlights are rescued from the wash rules and stay clearly visible in your printout",
6-
"Fixed: pages no longer keep a pale background halo at the edges — page borders are forced to paper white, so scanned-page edges stop wasting toner",
7-
"New: in the Arrange step you can now choose how many slide columns to pack per row — Auto, 2, 3 or 4 — for denser handouts or bigger slides (your choice is remembered)",
8-
"Fixed: a rare failure where a rendered page came out as one solid colour (all-black or all-white sheet) is now detected and automatically re-processed"
5+
"New — edit anytime: after processing, tap the new “Change layout & re-process” button (or click any earlier step in the progress bar) to go back, tweak the layout, page selection or ink settings, and process again — as many times as you like, without re-uploading your PDF",
6+
"Improved: repeated re-processing no longer keeps old output PDFs in memory, so many quick edits stay light on RAM"
97
],
108
"notes_hi": [
11-
"सुधरा — महत्वपूर्ण: ink-saving चालू होने पर हल्की नीली कलम की लकीरें ग़ायब हो जाया करती थीं। अब हल्की नीली लिखाई और हाइलाइट्स धुलाई के नियमों से बचा ली जाती हैं और प्रिंट में साफ़ दिखती हैं",
12-
"सुधरा: अब पन्नों के किनारों पर हल्का बैकग्राउंड नहीं रहता — किनारे सफ़ेद काग़ज़ जैसे सेट होते हैं, जिससे स्कैन किए पन्नों के बॉर्डर टोनर बर्बाद नहीं करते",
13-
"नया: Arrange चरण में अब चुन सकते हैं कि हर पंक्ति में कितने स्लाइड हों — Auto, 2, 3 या 4 — एक पन्ने पर ज़्यादा स्लाइड्स या बड़ी स्लाइड्स के लिए (आपकी पसंद याद रखी जाती है)",
14-
"सुधरा: कभी-कभार बना पन्ना पूरी तरह एक ही रंग का निकल जाता था (पूरा काला या सफ़ेद) — ऐप अब ऐसा पन्ना पकड़कर अपने-आप दोबारा प्रोसेस करता है"
9+
"नया — कभी भी बदलें: प्रोसेस करने के बाद नया “लेआउट बदलें और दोबारा बनाएँ” बटन दबाएँ (या प्रोग्रेस बार में कोई भी पिछला चरण चुनें), लेआउट/पेज/स्याही सेटिंग बदलें और दोबारा प्रोसेस करें — जितनी बार चाहें, बिना अपनी PDF दोबारा अपलोड किए",
10+
"सुधरा: बार-बार दोबारा प्रोसेस करने पर अब पुराना आउटपुट PDF मेमोरी में नहीं रहता — तेज़-तेज़ बदलावों पर भी ऐप हल्का चलता है"
1511
]
1612
}

‎src/components/printifier/result-step.tsx‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
RotateCcw,
2222
ScanText,
2323
Scissors,
24+
SlidersHorizontal,
2425
Smartphone,
2526
Type,
2627
Leaf,
@@ -137,6 +138,7 @@ export function ResultStep() {
137138
const layout = usePrintifyStore((s) => s.layout);
138139
const docs = usePrintifyStore((s) => s.docs);
139140
const reset = usePrintifyStore((s) => s.reset);
141+
const setStep = usePrintifyStore((s) => s.setStep);
140142

141143
// Smart download name — derives from the source document(s) + grid so a
142144
// week of downloads stops producing "notes-printifier (19) (1).pdf".
@@ -1045,6 +1047,16 @@ export function ResultStep() {
10451047
{waBusy ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <TelegramIcon className="mr-2 h-4 w-4" />}
10461048
{t('rs.tg')}
10471049
</Button>
1050+
<Button
1051+
type="button"
1052+
variant="outline"
1053+
size="lg"
1054+
onClick={() => setStep(3)}
1055+
aria-label={t('rs.tweak')}
1056+
className="w-full sm:w-auto"
1057+
>
1058+
<SlidersHorizontal className="mr-2 h-4 w-4" /> {t('rs.tweak')}
1059+
</Button>
10481060
<Button type="button" variant="outline" size="lg" onClick={reset} className="w-full sm:w-auto">
10491061
<RotateCcw className="mr-2 h-4 w-4" /> {t('rs.another')}
10501062
</Button>

‎src/components/printifier/stepper.tsx‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ export function Stepper() {
2222
const label = t(key);
2323
const isDone = i < step;
2424
const isCurrent = i === step;
25-
const clickable = i < step && step < 4;
25+
// Backward navigation is always allowed — including from the result
26+
// step (4), so users can revisit Arrange/Enhance/Layout and
27+
// re-process with different settings as often as they like.
28+
const clickable = i < step;
2629
return (
2730
<li key={key} className="flex items-center">
2831
<button

‎src/lib/i18n.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ export const DICT: Record<string, [string, string]> = {
417417
'rs.download': ['Download PDF', 'PDF डाउनलोड करें'],
418418
'rs.open': ['Open', 'खोलें'],
419419
'rs.another': ['Process another file', 'दूसरी फ़ाइल प्रोसेस करें'],
420+
'rs.tweak': ['Change layout & re-process', 'लेआउट बदलें और दोबारा बनाएँ'],
420421
'rs.bookletTitle': ['Booklet printing:', 'बुकलेट प्रिंटिंग:'],
421422
'rs.bookletBody': ['in the print dialog choose landscape + duplex with “flip on short edge”. Print the whole file, stack the sheets in order, fold once in the middle (the separator line is your fold guide) — done.', 'प्रिंट डायलॉग में लैंडस्केप + डुप्लेक्स चुनें, “flip on short edge” रखें। पूरी फ़ाइल प्रिंट करें, शीटें क्रम में रखें, बीच से मोड़ें (विभाजक रेखा मोड़ की निशानी है) — बस हो गया।'],
422423
'rs.duplexTitle': ['No duplex printer?', 'डुप्लेक्स प्रिंटर नहीं है?'],
@@ -1220,6 +1221,7 @@ export const EXTRA: Record<'mr' | 'ta' | 'bn' | 'gu' | 'pa', Record<string, stri
12201221
'rs.download': 'डाउनलोड',
12211222
'rs.open': 'उघडा',
12221223
'rs.another': 'नवीन PDF',
1224+
'rs.tweak': 'मांडणी बदला आणि पुन्हा तयार करा',
12231225
'rs.img.title': 'प्रतिमा म्हणून निर्यात',
12241226
'rs.img.btn': 'PNG निर्यात',
12251227
'rs.split.title': 'विभागून काढा',
@@ -2035,6 +2037,7 @@ export const EXTRA: Record<'mr' | 'ta' | 'bn' | 'gu' | 'pa', Record<string, stri
20352037
'rs.download': 'பதிவிறக்கு',
20362038
'rs.open': 'திற',
20372039
'rs.another': 'புதிய PDF',
2040+
'rs.tweak': 'அமைப்பை மாற்றி மீண்டும் உருவாக்கு',
20382041
'rs.img.title': 'படமாக ஏற்று',
20392042
'rs.img.btn': 'PNG ஏற்று',
20402043
'rs.split.title': 'பிரி',
@@ -2850,6 +2853,7 @@ export const EXTRA: Record<'mr' | 'ta' | 'bn' | 'gu' | 'pa', Record<string, stri
28502853
'rs.download': 'ডাউনলোড',
28512854
'rs.open': 'খুলুন',
28522855
'rs.another': 'নতুন PDF',
2856+
'rs.tweak': 'লেআউট বদলে আবার তৈরি করুন',
28532857
'rs.img.title': 'ছবি হিসেবে রপ্তানি',
28542858
'rs.img.btn': 'PNG রপ্তানি',
28552859
'rs.split.title': 'ভাগ করুন',
@@ -3665,6 +3669,7 @@ export const EXTRA: Record<'mr' | 'ta' | 'bn' | 'gu' | 'pa', Record<string, stri
36653669
'rs.download': 'PDF ડાઉનલોડ',
36663670
'rs.open': 'ખોલો',
36673671
'rs.another': 'બીજી ફાઇલ પ્રોસેસ કરો',
3672+
'rs.tweak': 'લેઆઉટ બદલો અને ફરી બનાવો',
36683673
'rs.img.title': 'છબીઓ તરીકે નિકાસ',
36693674
'rs.img.btn': 'PNG નિકાસ',
36703675
'rs.split.title': 'દરેક N પાનાંએ વહેંચો',
@@ -4480,6 +4485,7 @@ export const EXTRA: Record<'mr' | 'ta' | 'bn' | 'gu' | 'pa', Record<string, stri
44804485
'rs.download': 'PDF ਡਾਊਨਲੋਡ',
44814486
'rs.open': 'ਖੋਲ੍ਹੋ',
44824487
'rs.another': 'ਹੋਰ ਫ਼ਾਈਲ ਪ੍ਰੋਸੈਸ ਕਰੋ',
4488+
'rs.tweak': 'ਲੇਆਉਟ ਬਦਲੋ ਅਤੇ ਦੁਬਾਰਾ ਬਣਾਓ',
44834489
'rs.img.title': 'ਤਸਵੀਰਾਂ ਵਜੋਂ ਨਿਰਯਾਤ',
44844490
'rs.img.btn': 'PNG ਨਿਰਯਾਤ',
44854491
'rs.split.title': 'ਹਰ N ਪੰਨਿਆਂ ਤੇ ਵੰਡੋ',

‎src/lib/printify-store.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,10 @@ export const usePrintifyStore = create<PrintifyState>((set, get) => ({
12081208

12091209
const url = URL.createObjectURL(out.blob);
12101210
const result: ProcessResult = { ...out.result, url };
1211+
// Re-process loop: free the previous output's blob so editing the
1212+
// layout many times doesn't pile up object URLs in memory.
1213+
const prevUrl = get().result?.url;
1214+
if (prevUrl && prevUrl !== url) URL.revokeObjectURL(prevUrl);
12111215
// Impact meter BEFORE the step switch — ResultStep reads the totals on
12121216
// mount, and recordJob is a cheap synchronous localStorage write while
12131217
// the IndexedDB history saves below are async.

‎src/lib/version.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/** The running app version — keep in sync with public/version.json. */
2-
export const APP_VERSION = '2.3.0';
2+
export const APP_VERSION = '2.4.0';
33

44
/**
55
* Compare dotted versions; returns true when `remote` is NEWER than `local`.

0 commit comments

Comments
 (0)