Skip to content

Commit c576962

Browse files
committed
update files
1 parent 4d57a5b commit c576962

14 files changed

Lines changed: 899 additions & 1041 deletions

File tree

app.js

Lines changed: 50 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ if (window.matchMedia('(max-width: 1024px)').matches) {
1515
history.scrollRestoration = 'manual';
1616
}
1717
}
18-
/* ── HTML Entity Escaping Utility ── */
1918
function esc(s) {
2019
if (s == null) return '';
2120
return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
@@ -37,80 +36,28 @@ if (lastTab) {
3736
restoreTab();
3837
}
3938

40-
/* ── Global Application State ── */
39+
// ──State ────────────────────────────────────────────────
4140
const state = {
4241
enc: { files: [], blob: null, filename: null, isEncrypting: false, abort: false },
4342
dec: { file: null, blob: null, filename: null, unzippedFiles: null },
4443
recents: { enc: [], dec: [] }
4544
};
4645

47-
// Session-based history encryption helpers
48-
async function getHistoryKey() {
49-
let keyB64 = sessionStorage.getItem('fk_hist_key');
50-
if (!keyB64) {
51-
const key = crypto.getRandomValues(new Uint8Array(32));
52-
keyB64 = btoa(String.fromCharCode(...key));
53-
sessionStorage.setItem('fk_hist_key', keyB64);
54-
}
55-
const keyRaw = new Uint8Array([...atob(keyB64)].map(c => c.charCodeAt(0)));
56-
return crypto.subtle.importKey('raw', keyRaw, 'AES-GCM', false, ['encrypt', 'decrypt']);
57-
}
58-
59-
async function encryptHistory(data) {
60-
const key = await getHistoryKey();
61-
const iv = crypto.getRandomValues(new Uint8Array(12));
62-
const encoded = new TextEncoder().encode(JSON.stringify(data));
63-
const ciphertext = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, encoded);
64-
const combined = new Uint8Array(iv.length + ciphertext.byteLength);
65-
combined.set(iv);
66-
combined.set(new Uint8Array(ciphertext), iv.length);
67-
return btoa(String.fromCharCode(...combined));
68-
}
69-
70-
async function decryptHistory(encB64) {
71-
try {
72-
const key = await getHistoryKey();
73-
const raw = new Uint8Array([...atob(encB64)].map(c => c.charCodeAt(0)));
74-
const iv = raw.slice(0, 12);
75-
const ciphertext = raw.slice(12);
76-
const decrypted = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, key, ciphertext);
77-
return JSON.parse(new TextDecoder().decode(decrypted));
78-
} catch (e) { return null; }
79-
}
80-
81-
async function saveRecents() {
82-
const encrypted = await encryptHistory(state.recents);
83-
localStorage.setItem('fk_recents', encrypted);
84-
}
85-
86-
// Async load recents
87-
async function initRecents() {
46+
// Load recents from storage
47+
try {
8848
const stored = localStorage.getItem('fk_recents');
89-
if (!stored) return;
90-
const decrypted = await decryptHistory(stored);
91-
if (decrypted) {
92-
state.recents = decrypted;
93-
} else {
94-
try {
95-
const parsed = JSON.parse(stored);
96-
if (parsed.enc || parsed.dec) {
97-
state.recents = parsed;
98-
await saveRecents();
99-
}
100-
} catch (e) { }
49+
if (stored) {
50+
const parsed = JSON.parse(stored);
51+
if (parsed.enc) state.recents.enc = parsed.enc;
52+
if (parsed.dec) state.recents.dec = parsed.dec;
10153
}
102-
renderRecents('enc');
103-
renderRecents('dec');
104-
}
105-
initRecents();
54+
} catch (e) { }
10655

107-
/* ── Encryption Constants & Magic Numbers ── */
108-
const MAGIC = new Uint8Array([0x46, 0x4B, 0x52, 0x59, 0x50, 0x54, 0x31]); // "FKRYPT1"
56+
// Magic bytes to identify .enc format (ASCII "FKRYPT1")
57+
const MAGIC = new Uint8Array([0x46, 0x4B, 0x52, 0x59, 0x50, 0x54, 0x31]);
10958
const PBKDF2_ITERS = 310_000;
11059
const SALT_LEN = 32;
11160
const IV_LEN = 12;
112-
113-
/* ── UI Icons ── */
11461
const ICON_EYE = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0z"/><circle cx="12" cy="12" r="3"/></svg>`;
11562
const ICON_EYE_OFF = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"/><path d="M6.61 6.61A13.52 13.52 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 1.55-.12"/><path d="M22 22 2 2"/><path d="M9.88 9.88a3 3 0 1 0 4.24 4.24"/></svg>`;
11663

@@ -154,20 +101,17 @@ function switchTab(tab) {
154101
localStorage.setItem('fk_active_tab', tab);
155102
}
156103

157-
/* ── Drag & Drop Event Handlers ── */
104+
// ── Drag & drop ──────────────────────────────────────────
158105
function onDragOver(e) {
159106
e.preventDefault();
160107
e.currentTarget.classList.add('drag-over');
161108
}
162109
function onDragLeave(e) {
163110
e.currentTarget.classList.remove('drag-over');
164111
}
165-
166-
/* ── File Size & Limit Constants ── */
167112
const MAX_FILES = 1;
168113
const MAX_SIZE_BYTES = 2 * 1024 * 1024 * 1024; // 2GB limit
169114

170-
/* ── File Selection Handlers ── */
171115
function onDrop(e, mode) {
172116
e.preventDefault();
173117
e.currentTarget.classList.remove('drag-over');
@@ -179,7 +123,6 @@ function onFileSelect(e, mode) {
179123
if (fileList.length) { applyFiles(fileList, mode); }
180124
}
181125

182-
/* ── Process Selected Files ── */
183126
function applyFiles(fileList, mode, append = false) {
184127
if (mode === 'enc') {
185128
let newFiles = Array.from(fileList).filter(f => {
@@ -199,8 +142,6 @@ function applyFiles(fileList, mode, append = false) {
199142
}
200143
state.enc.files = combined;
201144
showEncPreview(state.enc.files);
202-
// Reset encryption flow UI when new files are selected
203-
if (typeof resetEncryptFlow === 'function') resetEncryptFlow();
204145
} else {
205146
const file = fileList[0];
206147
if (file && !file.name.toLowerCase().endsWith('.enc')) {
@@ -314,8 +255,6 @@ function fmtSize(n) {
314255

315256
function truncateName(name, limit = 14, show = 11) {
316257
if (!name) return '';
317-
// Show full name if on desktop (width > 1024px)
318-
if (!window.matchMedia('(max-width: 1024px)').matches) return name;
319258
return name.length > limit ? name.substring(0, show) + '...' : name;
320259
}
321260

@@ -412,8 +351,6 @@ async function deriveKey(password, salt) {
412351
const enc = new TextEncoder();
413352
const raw = enc.encode(password);
414353
const keyMat = await crypto.subtle.importKey('raw', raw, 'PBKDF2', false, ['deriveKey']);
415-
// Zero out the raw password buffer immediately after use
416-
raw.fill(0);
417354
return crypto.subtle.deriveKey(
418355
{ name: 'PBKDF2', salt, iterations: PBKDF2_ITERS, hash: 'SHA-256' },
419356
keyMat,
@@ -670,9 +607,7 @@ function handleTouchHover(e) {
670607
clientY: touch.clientY,
671608
target: btn,
672609
getBoundingClientRect: () => btn.getBoundingClientRect(),
673-
querySelector: (sel) => btn.querySelector(sel),
674-
preventDefault: () => {},
675-
stopPropagation: () => {}
610+
querySelector: (sel) => btn.querySelector(sel)
676611
};
677612
// For simple inline handlers that use 'event'
678613
window.event = fakeEvent;
@@ -740,12 +675,12 @@ document.addEventListener('touchend', (e) => {
740675
renderRecents('dec');
741676
})();
742677

743-
/* ─── Recents ────────────────────────────────────────────── */
744-
async function addRecent(mode, data) {
678+
// ─── Recents ──────────────────────────────────────────────
679+
function addRecent(mode, data) {
745680
const item = { ...data, id: Date.now() };
746681
state.recents[mode].unshift(item);
747682
state.recents[mode] = state.recents[mode].slice(0, 30); // Keep last 30
748-
await saveRecents();
683+
localStorage.setItem('fk_recents', JSON.stringify(state.recents));
749684
renderRecents(mode);
750685
}
751686

@@ -788,15 +723,15 @@ function renderRecents(mode) {
788723
}).join('');
789724
}
790725

791-
async function clearRecents(mode) {
726+
function clearRecents(mode) {
792727
state.recents[mode] = [];
793-
await saveRecents();
728+
localStorage.setItem('fk_recents', JSON.stringify(state.recents));
794729
renderRecents(mode);
795730
}
796731

797-
async function removeRecent(mode, id) {
732+
function removeRecent(mode, id) {
798733
state.recents[mode] = state.recents[mode].filter(item => item.id !== id);
799-
await saveRecents();
734+
localStorage.setItem('fk_recents', JSON.stringify(state.recents));
800735
renderRecents(mode);
801736
toast('info', 'Item removed from history.');
802737
}
@@ -1209,7 +1144,36 @@ document.querySelectorAll('.scroll-reveal').forEach(el => {
12091144

12101145
// ─── Mobile Back Button Handling ───
12111146
window.pushModalState = function () {
1212-
// Disabled as per user request for direct back navigation
1147+
// Push a dummy state so back button can be intercepted
1148+
history.pushState({ modalOpen: true }, "");
12131149
};
12141150

1215-
// popstate listener removed as per user request for direct back navigation
1151+
window.addEventListener('popstate', function (e) {
1152+
// Sidebars
1153+
['recents-wrapper', 'tutorial-wrapper', 'cp-wrapper'].forEach(id => {
1154+
if (typeof window.hideSidebarBox === 'function') {
1155+
const el = document.getElementById(id);
1156+
if (el && !el.classList.contains('hidden')) {
1157+
window.hideSidebarBox(id);
1158+
}
1159+
}
1160+
});
1161+
1162+
// Previews
1163+
if (typeof updateEncSidebarPreview === 'function') {
1164+
const encCard = document.getElementById('enc-preview-card');
1165+
if (encCard && !encCard.classList.contains('hidden')) updateEncSidebarPreview(null);
1166+
}
1167+
if (typeof updateDecSidebarPreview === 'function') {
1168+
const decCard = document.getElementById('dec-preview-card');
1169+
if (decCard && !decCard.classList.contains('hidden')) updateDecSidebarPreview(null);
1170+
}
1171+
1172+
// Tutorial Modal
1173+
if (typeof closeTutorialModal === 'function') {
1174+
const tutModal = document.getElementById('tutorial-modal');
1175+
if (tutModal && tutModal.classList.contains('active')) {
1176+
closeTutorialModal();
1177+
}
1178+
}
1179+
});

background/bgchecker.css

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,24 @@
1-
/* ── Background Grid & Interactive Spotlights ── */
1+
/* ── Background decorations ── */
22
.bg-grid {
33
position: fixed;
44
inset: 0;
55
z-index: 0;
66
pointer-events: none;
7-
/* Premium Checker Design: One Fade (0.02), One Normal (0.1) */
87
background-image:
9-
conic-gradient(rgba(142, 182, 155, 0.1) 0deg 90deg,
10-
rgba(142, 182, 155, 0.02) 90deg 180deg,
11-
rgba(142, 182, 155, 0.1) 180deg 270deg,
12-
rgba(142, 182, 155, 0.02) 270deg);
13-
background-size: 100px 100px;
14-
background-position: 0 0;
15-
/* Mask image creates the mouse-following spotlight effect */
16-
-webkit-mask-image: radial-gradient(circle 500px at var(--mouseX, 50vw) var(--mouseY, 50vh), black 0%, transparent 100%);
17-
mask-image: radial-gradient(circle 500px at var(--mouseX, 50vw) var(--mouseY, 50vh), black 0%, transparent 100%);
8+
linear-gradient(rgba(142, 182, 155, 0.18) 1px, transparent 1px),
9+
linear-gradient(90deg, rgba(142, 182, 155, 0.18) 1px, transparent 1px);
10+
background-size: 60px 60px;
11+
-webkit-mask-image: radial-gradient(circle 350px at var(--mouseX, 50vw) var(--mouseY, 50vh), black 0%, transparent 100%);
12+
mask-image: radial-gradient(circle 350px at var(--mouseX, 50vw) var(--mouseY, 50vh), black 0%, transparent 100%);
1813
transition: opacity var(--trans);
1914
}
2015

21-
/* ── Decrypt Mode Background Variation ── */
2216
body.decrypt-mode .bg-grid {
2317
background-image:
24-
conic-gradient(rgba(232, 220, 196, 0.08) 0deg 90deg,
25-
rgba(232, 220, 196, 0.02) 90deg 180deg,
26-
rgba(232, 220, 196, 0.08) 180deg 270deg,
27-
rgba(232, 220, 196, 0.02) 270deg);
18+
linear-gradient(rgba(255, 247, 230, 0.08) 1px, transparent 1px),
19+
linear-gradient(90deg, rgba(255, 247, 230, 0.08) 1px, transparent 1px);
2820
}
2921

30-
/* ── Why Section Title Hover Effect ── */
3122
.why-title-wrapper {
3223
position: relative;
3324
display: inline-block;
@@ -45,13 +36,11 @@ body.decrypt-mode .bg-grid {
4536
white-space: nowrap;
4637
}
4738

48-
/* Static text layer */
4939
.main-layer {
5040
position: relative;
5141
z-index: 1;
5242
}
5343

54-
/* Hover reveal layer (flashlight effect) */
5544
.hover-layer {
5645
position: absolute;
5746
top: 0;
@@ -66,7 +55,6 @@ body.decrypt-mode .bg-grid {
6655
transition: none;
6756
}
6857

69-
/* ── Typography Colors ── */
7058
.why-accent {
7159
color: var(--accent);
7260
}
@@ -91,7 +79,6 @@ body.decrypt-mode .hover-layer .why-white {
9179
/* 'Why' and 'Krypt' turn white when hovered */
9280
}
9381

94-
/* ── Mobile & Tablet Responsiveness ── */
9582
@media (max-width: 1024px) {
9683
.bg-grid {
9784
animation: none !important;
@@ -116,4 +103,4 @@ body.decrypt-mode .hover-layer .why-white {
116103
.bg-grid::after {
117104
display: none !important;
118105
}
119-
}
106+
}

fflate.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<meta charset="UTF-8" />
66
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: blob:; connect-src 'self' https://fonts.googleapis.com https://fonts.gstatic.com; worker-src 'self' blob:; frame-src 'self' blob:;">
77
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
8-
<title>FileKrypt</title>
8+
<title>About FileKrypt</title>
99
<meta name="description"
1010
content="Learn more about FileKrypt – the secure, private, and local-only file encryption tool. No data ever leaves your browser." />
1111
<link rel="icon" type="image/svg+xml" href="assets/KryptLogo.svg">
@@ -18,7 +18,9 @@
1818

1919
<link rel="stylesheet" href="style.css" />
2020
<link rel="stylesheet" href="loader/loader.css" />
21-
<link rel="stylesheet" href="background/bgchecker.css" />
21+
22+
23+
2224
<link rel='stylesheet' href='index/index_style.css'>
2325
</head>
2426

index/index_script.js

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -373,18 +373,5 @@
373373
alert('Link copied to clipboard!');
374374
}
375375
}
376+
376377

377-
// Ensure loader is hidden when navigating back to this page (bfcache support)
378-
window.addEventListener('pageshow', (event) => {
379-
const loader = document.getElementById('page-loader');
380-
if (loader) {
381-
loader.style.display = 'none';
382-
loader.style.opacity = '0';
383-
}
384-
});
385-
386-
// Hide loader before leaving the page to ensure it's hidden if the page is cached
387-
window.addEventListener('beforeunload', () => {
388-
const loader = document.getElementById('page-loader');
389-
if (loader) loader.style.display = 'none';
390-
});

0 commit comments

Comments
 (0)