From 191b54f113f8884ac40281ddc7e3545b436e54a7 Mon Sep 17 00:00:00 2001 From: lelo Date: Fri, 30 May 2025 09:32:28 +0000 Subject: [PATCH 1/9] attempt to fix pwa updates --- app.py | 1 + static/sw.js | 62 ++++++++++++++++++++++++++++++++-------------- templates/app.html | 6 ++--- 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/app.py b/app.py index a3756c9..4ae4d8b 100755 --- a/app.py +++ b/app.py @@ -238,6 +238,7 @@ def custom_logo(filename): response.headers['Cache-Control'] = 'public, max-age=86400' return response + @app.route('/sw.js') def serve_sw(): return send_from_directory(os.path.join(app.root_path, 'static'), 'sw.js', mimetype='application/javascript') diff --git a/static/sw.js b/static/sw.js index baf4cee..6ed70ce 100644 --- a/static/sw.js +++ b/static/sw.js @@ -1,30 +1,56 @@ -const cacheName = 'gottesdienste-v1.11'; +const VERSION = '1.18'; +const CACHE_NAME = `gottesdienste-v${VERSION}`; const assets = [ - '/', - '/static/app.css', - '/static/app.js', - '/static/gallery.css', - '/static/gallery.js', - '/static/audioplayer.css', - '/static/audioplayer.js', + '/', + `/static/app.css?v=${VERSION}`, + `/static/app.js?v=${VERSION}`, + `/static/gallery.css?v=${VERSION}`, + `/static/gallery.js?v=${VERSION}`, + `/static/audioplayer.css?v=${VERSION}`, + `/static/audioplayer.js?v=${VERSION}`, '/icon/logo-192x192.png', + '/icon/logo-300x300.png', '/icon/logo-512x512.png', '/custom_logo/logoB.png', '/custom_logo/logoW.png' ]; -self.addEventListener('install', e => { - e.waitUntil( - caches.open(cacheName).then(cache => { - return cache.addAll(assets); +self.addEventListener('install', evt => { + self.skipWaiting(); + evt.waitUntil( + caches.open(CACHE_NAME) + .then(cache => cache.addAll(assets)) + ); +}); + +self.addEventListener('activate', evt => { + self.clients.claim(); + evt.waitUntil( + caches.keys().then(keys => + Promise.all( + keys + .filter(k => k !== CACHE_NAME) + .map(k => caches.delete(k)) + ) + ) + .then(() => { + // Reload to use new files + return self.clients.matchAll({ type: 'window' }) + .then(clients => + clients.forEach(client => client.navigate(client.url)) + ); }) ); }); -self.addEventListener('fetch', e => { - e.respondWith( - caches.match(e.request).then(response => { - return response || fetch(e.request); - }) +self.addEventListener('fetch', evt => { + if (evt.request.mode === 'navigate') { + evt.respondWith( + fetch(evt.request).catch(() => caches.match('/app.html')) + ); + return; + } + evt.respondWith( + caches.match(evt.request).then(cached => cached || fetch(evt.request)) ); -}); \ No newline at end of file +}); diff --git a/templates/app.html b/templates/app.html index 5a582a6..a98e78d 100644 --- a/templates/app.html +++ b/templates/app.html @@ -8,7 +8,7 @@ - + @@ -23,7 +23,7 @@ - + @@ -253,8 +253,6 @@ if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('{{ url_for("static", filename="sw.js") }}') - .then(reg => console.log('Service worker registered.', reg)) - .catch(err => console.error('Service worker not registered.', err)); }); } From 17c8a41229e9054db33bed88c2bb8d1c046bb902 Mon Sep 17 00:00:00 2001 From: lelo Date: Fri, 30 May 2025 09:47:06 +0000 Subject: [PATCH 2/9] cleanup --- app.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app.py b/app.py index 4ae4d8b..2d77cdb 100755 --- a/app.py +++ b/app.py @@ -466,7 +466,7 @@ def serve_file(subpath): filesize = os.path.getsize(file_path) # Figure out download flag and filename - ask_download = request.args.get('download') == 'true' + as_attachment = request.args.get('download') == 'true' filename = os.path.basename(full_path) # Single send_file call with proper attachment handling @@ -474,10 +474,10 @@ def serve_file(subpath): file_path, mimetype=mime, conditional=True, - as_attachment=ask_download, - download_name=filename if ask_download else None + as_attachment=as_attachment , + download_name=filename if as_attachment else None ) - if not ask_download: + if not as_attachment : response.headers['Content-Disposition'] = 'inline' response.headers['Cache-Control'] = 'public, max-age=86400' From b35e4030ace54edd81a555f910163cda983efb9c Mon Sep 17 00:00:00 2001 From: lelo Date: Fri, 30 May 2025 10:03:19 +0000 Subject: [PATCH 3/9] try fixing download --- app.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/app.py b/app.py index 2d77cdb..3e1391d 100755 --- a/app.py +++ b/app.py @@ -468,15 +468,27 @@ def serve_file(subpath): # Figure out download flag and filename as_attachment = request.args.get('download') == 'true' filename = os.path.basename(full_path) + + if as_attachment: + download_name = filename + mimetype = 'application/octet-stream' + else: + download_name = None + mimetype = mime + # Single send_file call with proper attachment handling response = send_file( file_path, - mimetype=mime, + mimetype=mimetype, conditional=True, as_attachment=as_attachment , - download_name=filename if as_attachment else None + download_name=download_name ) + + if as_attachment: + response.headers['X-Content-Type-Options'] = 'nosniff' + if not as_attachment : response.headers['Content-Disposition'] = 'inline' response.headers['Cache-Control'] = 'public, max-age=86400' From 13cb4fecbbcc79759c26df8d475e98d84970007c Mon Sep 17 00:00:00 2001 From: lelo Date: Fri, 30 May 2025 10:30:06 +0000 Subject: [PATCH 4/9] cleanup --- app.py | 5 +++-- static/sw.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app.py b/app.py index 3e1391d..d7ecfa0 100755 --- a/app.py +++ b/app.py @@ -488,9 +488,10 @@ def serve_file(subpath): if as_attachment: response.headers['X-Content-Type-Options'] = 'nosniff' - - if not as_attachment : + response.headers['Content-Disposition'] = 'attachment' + else: response.headers['Content-Disposition'] = 'inline' + response.headers['Cache-Control'] = 'public, max-age=86400' # 7) Logging diff --git a/static/sw.js b/static/sw.js index 6ed70ce..afb2215 100644 --- a/static/sw.js +++ b/static/sw.js @@ -1,4 +1,4 @@ -const VERSION = '1.18'; +const VERSION = '1.19'; const CACHE_NAME = `gottesdienste-v${VERSION}`; const assets = [ '/', From 5345331637d50dfdcef3edbf718b38cd673a45b1 Mon Sep 17 00:00:00 2001 From: lelo Date: Sun, 1 Jun 2025 20:30:22 +0000 Subject: [PATCH 5/9] remove unproven edit --- static/audioplayer.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/static/audioplayer.js b/static/audioplayer.js index c0f25b8..9d45329 100644 --- a/static/audioplayer.js +++ b/static/audioplayer.js @@ -150,8 +150,6 @@ class SimpleAudioPlayer { // Create a “real” link to that URL and click it const a = document.createElement('a'); a.href = downloadUrl.toString(); - a.download = ''; // tell Safari “this is a download” - a.target = '_blank'; // force a real navigation on iOS // NOTE: do NOT set a.download here – we want the server's Content-Disposition to drive it document.body.appendChild(a); a.click(); From 20e65f4c696aaee3e501fdcba45af4597d2b967c Mon Sep 17 00:00:00 2001 From: lelo Date: Tue, 3 Jun 2025 19:11:24 +0000 Subject: [PATCH 6/9] fix --- analytics.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/analytics.py b/analytics.py index eccc8b7..b16ebc6 100644 --- a/analytics.py +++ b/analytics.py @@ -615,6 +615,8 @@ def file_access(): start_dt = now - timedelta(hours=24) elif session['timeframe'] == '7days': start_dt = now - timedelta(days=7) + elif session['timeframe'] == '14days': + start_dt = now - timedelta(days=14) elif session['timeframe'] == '30days': start_dt = now - timedelta(days=30) elif session['timeframe'] == '365days': From 1b374b667e24835805a355b70e9d50f3caac67fe Mon Sep 17 00:00:00 2001 From: lelo Date: Tue, 3 Jun 2025 19:16:37 +0000 Subject: [PATCH 7/9] add wildcards in blocked_filenames --- app.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app.py b/app.py index d7ecfa0..d6a1857 100755 --- a/app.py +++ b/app.py @@ -24,6 +24,7 @@ import auth import analytics as a import folder_secret_config_editor as fsce import helperfunctions as hf +import fnmatch app_config = auth.return_app_config() BASE_DIR = os.path.realpath(app_config['BASE_DIR']) @@ -136,7 +137,7 @@ def list_directory_contents(directory, subpath): music_exts = ('.mp3',) image_exts = ('.jpg', '.jpeg', '.png', '.gif', '.bmp') - blocked_filenames = ['Thumbs.db'] + blocked_filenames = ['Thumbs.db', '*.mrk'] try: with os.scandir(directory) as it: @@ -146,8 +147,8 @@ def list_directory_contents(directory, subpath): if entry.name.startswith('.'): continue - # Skip blocked_filenames - if entry.name in blocked_filenames: + # Skip blocked_filenames using fnmatch for wildcards + if any(fnmatch.fnmatch(entry.name, pattern) for pattern in blocked_filenames): continue if entry.is_dir(follow_symlinks=False): From 27e42a4e9731ca33c9738e98846891dbc30dc37b Mon Sep 17 00:00:00 2001 From: lelo Date: Tue, 3 Jun 2025 19:17:40 +0000 Subject: [PATCH 8/9] add .ai folder to skip --- app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.py b/app.py index d6a1857..f242598 100755 --- a/app.py +++ b/app.py @@ -152,7 +152,7 @@ def list_directory_contents(directory, subpath): continue if entry.is_dir(follow_symlinks=False): - if entry.name in ["Transkription", "@eaDir"]: + if entry.name in ["Transkription", "@eaDir", ".ai"]: continue rel_path = os.path.join(subpath, entry.name) if subpath else entry.name From 6c9da444da0fcc52d294cb8c2700cce4585b1d48 Mon Sep 17 00:00:00 2001 From: lelo Date: Sun, 8 Jun 2025 08:49:59 +0000 Subject: [PATCH 9/9] fix categories --- helperfunctions.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/helperfunctions.py b/helperfunctions.py index 4c9f17e..b81888d 100644 --- a/helperfunctions.py +++ b/helperfunctions.py @@ -54,8 +54,10 @@ def extract_date_from_string(string_with_date): def extract_structure_from_string(input_string): # extract category and titel from filename - filename_ext = os.path.splitext(input_string)[0] + filepathname_ext = os.path.splitext(input_string)[0] # remove file extension + filename_ext = os.path.basename(filepathname_ext) # get only the filename left_side, right_side = filename_ext.split('-', 1) if '-' in filename_ext else (filename_ext, None) + try: int(left_side.strip()) # first part is only a number @@ -65,9 +67,9 @@ def extract_structure_from_string(input_string): # first part not a number pass - if 'predig' in left_side.lower(): + if 'predig' in left_side.lower() or 'thema' in left_side.lower(): category = 'Predigt' - elif 'wort' in left_side.lower() or 'einladung' in left_side.lower() or 'begrüßung' in left_side.lower() or 'ansprache' in left_side.lower() or 'einleitung' in left_side.lower(): + elif 'wort' in left_side.lower() or 'einladung' in left_side.lower() or 'begrüßung' in left_side.lower() or 'ansprache' in left_side.lower() or 'einleitung' in left_side.lower() or 'aufruf zum' in left_side.lower() or 'zuruf zum' in left_side.lower(): category = 'Vorwort' elif 'kinderchor' in left_side.lower(): category = 'Kinderchor'