diff --git a/app.py b/app.py index 9e4b1aa..096395c 100644 --- a/app.py +++ b/app.py @@ -56,7 +56,7 @@ def media_list_clear_cache(): if GStorage["scaning_state"] == "inprogress": return jsonify({"status": True}) - + media_remove_cache(config["cache_dir"], GStorage) scan_medialib(config, GStorage, socketio) return jsonify({"status": True}) @@ -68,7 +68,7 @@ if filtered_files == None: filtered_files = scan_medialib(config, GStorage, socketio) - if GStorage["scaning_state"] == "inprogress" and not len(filtered_files): + if GStorage["scaning_state"] == "inprogress" and filtered_files != None and not len(filtered_files): response = {"status": "scaning", "data": []}; else: response = {"status": True, "data": filtered_files} diff --git a/mediascan.py b/mediascan.py index b9188f7..af2fe09 100644 --- a/mediascan.py +++ b/mediascan.py @@ -138,13 +138,18 @@ # Function to list media files -def list_media_files(directories): +def list_media_files(socketio, directories): media_files = [] for directory in directories: if os.path.exists(directory): for root, _, files in os.walk(directory): - for file in files: + for inx, file in enumerate(files): file_path = os.path.join(root, file) + + if not inx or not inx % 50: + socketio.emit("medialib-scaning-process", { + "message": f"Scaning: { directory }" + }) try: file_info = { "name": file, @@ -202,14 +207,24 @@ def bg_scan_medialib(socketio, config, GStorage): GStorage["scaning_state"] = "inprogress"; - media_files = list_media_files(config.get("directories", [])) + media_files = list_media_files(socketio, config.get("directories", [])) allowed_formats = config.get("allowed_formats", []) + socketio.emit("medialib-scaning-process", { + "message": f"Filtering by file extension..." + }) filtered_files = filter_media_files(media_files, allowed_formats) + socketio.emit("medialib-scaning-process", { + "message": f"Adding media file detail..." + }) + # Add detailed media info for file in filtered_files: file["size"], file["size_unit"], file["size_bytes"] = human_readable_size(file["size"]) + socketio.emit("medialib-scaning-process", { + "message": f"Adding detail: { file["path"] }" + }) file_info = get_media_info_with_ffprobe(file["path"]) if file_info: file["info"] = file_info @@ -218,6 +233,9 @@ GStorage["scaning_state"] = "inaction" + socketio.emit("medialib-scaning-process", { + "message": f"Creating cache..." + }) media_create_cache(config["cache_dir"], filtered_files) socketio.emit("medialib-scaning-complete", { diff --git a/scss/components/media-list.scss b/scss/components/media-list.scss new file mode 100644 index 0000000..74e3e24 --- /dev/null +++ b/scss/components/media-list.scss @@ -0,0 +1,13 @@ +.component.media-list { + .do-rescan-media-lib { + .spinner-border { + display: none; + } + + &.inprogress { + .spinner-border { + display: block; + } + } + } +} \ No newline at end of file diff --git a/scss/index.scss b/scss/index.scss index 360b4cc..8595abf 100644 --- a/scss/index.scss +++ b/scss/index.scss @@ -1 +1,2 @@ -@import "main.scss"; \ No newline at end of file +@import "main.scss"; +@import "components/media-list.scss"; \ No newline at end of file diff --git a/scss/main.scss b/scss/main.scss index 2d58f16..f44096a 100644 --- a/scss/main.scss +++ b/scss/main.scss @@ -92,3 +92,22 @@ align-items: center; } +.sm-spinner { + width: 18px; + height: 18px; + border-width: 3px; +} + +.btn { + .border-spinner { + margin-right: 2px; + position: relative; + top: 1px; + } + + &.inprogress { + display: inline-flex; + gap: 6px; + align-items: center; + } +} \ No newline at end of file diff --git a/static/css/main.css b/static/css/main.css index 928b5d3..78c5b6b 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -1,2 +1,2 @@ -a{text-decoration:none}.loading-spinner-container{width:100%;margin:50px auto;text-align:center}.loader{width:48px;height:48px;border:5px solid #777;border-bottom-color:transparent;border-radius:50%;display:inline-block;box-sizing:border-box;animation:rotation 1s linear infinite}@keyframes rotation{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.transcodate-form-container{margin-top:20px;display:flex;flex-wrap:wrap;flex-direction:row;gap:10px}.transcodate-form-container>.form-control{display:flex;flex-wrap:nowrap;flex-direction:row;justify-content:flex-start;gap:10px;align-items:center}.transcodate-form-container>.form-control>strong{white-space:nowrap;display:inline-block;width:100px}.crf-range{margin-left:5px}#progress{margin-top:20px;margin-bottom:0}.circle-bg{stroke-dasharray:100,100}.circle-progress{transition:stroke-dasharray .3s ease}.list-group-item.task{display:flex;flex-direction:row;justify-content:space-between;align-items:center;gap:12px}.list-group-item.task .file{display:flex;flex-direction:row;gap:8px;align-items:center} +a{text-decoration:none}.loading-spinner-container{width:100%;margin:50px auto;text-align:center}.loader{width:48px;height:48px;border:5px solid #777;border-bottom-color:transparent;border-radius:50%;display:inline-block;box-sizing:border-box;animation:rotation 1s linear infinite}@keyframes rotation{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.transcodate-form-container{margin-top:20px;display:flex;flex-wrap:wrap;flex-direction:row;gap:10px}.transcodate-form-container>.form-control{display:flex;flex-wrap:nowrap;flex-direction:row;justify-content:flex-start;gap:10px;align-items:center}.transcodate-form-container>.form-control>strong{white-space:nowrap;display:inline-block;width:100px}.crf-range{margin-left:5px}#progress{margin-top:20px;margin-bottom:0}.circle-bg{stroke-dasharray:100,100}.circle-progress{transition:stroke-dasharray .3s ease}.list-group-item.task{display:flex;flex-direction:row;justify-content:space-between;align-items:center;gap:12px}.list-group-item.task .file{display:flex;flex-direction:row;gap:8px;align-items:center}.sm-spinner{width:18px;height:18px;border-width:3px}.btn .border-spinner{margin-right:2px;position:relative;top:1px}.btn.inprogress{display:inline-flex;gap:6px;align-items:center}.component.media-list .do-rescan-media-lib .spinner-border{display:none}.component.media-list .do-rescan-media-lib.inprogress .spinner-border{display:block} /*# sourceMappingURL=main.css.map */ diff --git a/static/css/main.css.map b/static/css/main.css.map index 01c5d37..0e36f16 100644 --- a/static/css/main.css.map +++ b/static/css/main.css.map @@ -1 +1 @@ -{"version":3,"sources":["main.scss"],"names":[],"mappings":"AAAA,EACE,gBAAA,KAKF,2BACC,MAAA,KACA,OAAA,KAAA,KACA,WAAA,OAGD,QACE,MAAA,KACA,OAAA,KACA,OAAA,IAAA,MAAA,KACA,oBAAA,YACA,cAAA,IACA,QAAA,aACA,WAAA,WACA,UAAA,SAAA,GAAA,OAAA,SAGF,oBACE,GACE,UAAA,UAGF,KACE,UAAA,gBAMJ,4BACC,WAAA,KACA,QAAA,KACA,UAAA,KACC,eAAA,IACA,IAAA,KAGF,0CACC,QAAA,KACA,UAAA,OACC,eAAA,IACA,gBAAA,WACA,IAAA,KACA,YAAA,OAGF,iDACC,YAAA,OACA,QAAA,aACC,MAAA,MAGF,WACE,YAAA,IAGF,UACE,WAAA,KACA,cAAA,EAOF,WACE,iBAAA,GAAA,CAAA,IAGF,iBACE,WAAA,iBAAA,IAAA,KAGF,sBACE,QAAA,KACA,eAAA,IACA,gBAAA,cACA,YAAA,OACA,IAAA,KAGF,4BACE,QAAA,KACA,eAAA,IACA,IAAA,IACA,YAAA","file":"main.css","sourcesContent":["a {\n text-decoration: none;\n}\n\n/* LOADING SPINNER */\n\n.loading-spinner-container {\n\twidth: 100%;\n\tmargin: 50px auto;\n\ttext-align: center;\n}\n\n.loader {\n width: 48px;\n height: 48px;\n border: 5px solid #777;\n border-bottom-color: transparent;\n border-radius: 50%;\n display: inline-block;\n box-sizing: border-box;\n animation: rotation 1s linear infinite;\n}\n\n@keyframes rotation {\n 0% {\n transform: rotate(0deg);\n }\n\n 100% {\n transform: rotate(360deg);\n }\n} \n\n/* END LOADING SPINNER */\n\n.transcodate-form-container {\n\tmargin-top: 20px;\n\tdisplay: flex;\n\tflex-wrap: wrap;\n flex-direction: row;\n gap: 10px;\n}\n\n.transcodate-form-container > .form-control {\n\tdisplay: flex;\n\tflex-wrap: nowrap;\n flex-direction: row;\n justify-content: flex-start;\n gap: 10px;\n align-items: center;\n}\n\n.transcodate-form-container > .form-control > strong {\n\twhite-space: nowrap;\n\tdisplay: inline-block;\n width: 100px;\n}\n\n.crf-range {\n margin-left: 5px;\n}\n\n#progress {\n margin-top: 20px;\n margin-bottom: 0;\n}\n\n.progress-circle {\n/* transform: rotate(-90deg);*/\n}\n\n.circle-bg {\n stroke-dasharray: 100, 100;\n}\n\n.circle-progress {\n transition: stroke-dasharray 0.3s ease;\n}\n\n.list-group-item.task {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n}\n\n.list-group-item.task .file {\n display: flex;\n flex-direction: row;\n gap: 8px;\n align-items: center;\n}\n\n"]} \ No newline at end of file +{"version":3,"sources":["main.scss","components/media-list.scss"],"names":[],"mappings":"AAAA,EACE,gBAAA,KAKF,2BACC,MAAA,KACA,OAAA,KAAA,KACA,WAAA,OAGD,QACE,MAAA,KACA,OAAA,KACA,OAAA,IAAA,MAAA,KACA,oBAAA,YACA,cAAA,IACA,QAAA,aACA,WAAA,WACA,UAAA,SAAA,GAAA,OAAA,SAGF,oBACE,GACE,UAAA,UAGF,KACE,UAAA,gBAMJ,4BACC,WAAA,KACA,QAAA,KACA,UAAA,KACC,eAAA,IACA,IAAA,KAGF,0CACC,QAAA,KACA,UAAA,OACC,eAAA,IACA,gBAAA,WACA,IAAA,KACA,YAAA,OAGF,iDACC,YAAA,OACA,QAAA,aACC,MAAA,MAGF,WACE,YAAA,IAGF,UACE,WAAA,KACA,cAAA,EAOF,WACE,iBAAA,GAAA,CAAA,IAGF,iBACE,WAAA,iBAAA,IAAA,KAGF,sBACE,QAAA,KACA,eAAA,IACA,gBAAA,cACA,YAAA,OACA,IAAA,KAGF,4BACE,QAAA,KACA,eAAA,IACA,IAAA,IACA,YAAA,OAGF,YACE,MAAA,KACA,OAAA,KACA,aAAA,IAIA,qBACE,aAAA,IACA,SAAA,SACA,IAAA,IAGF,gBACE,QAAA,YACA,IAAA,IACA,YAAA,OC5GF,2DACC,QAAA,KAIA,sEACC,QAAA","file":"main.css","sourcesContent":["a {\n text-decoration: none;\n}\n\n/* LOADING SPINNER */\n\n.loading-spinner-container {\n\twidth: 100%;\n\tmargin: 50px auto;\n\ttext-align: center;\n}\n\n.loader {\n width: 48px;\n height: 48px;\n border: 5px solid #777;\n border-bottom-color: transparent;\n border-radius: 50%;\n display: inline-block;\n box-sizing: border-box;\n animation: rotation 1s linear infinite;\n}\n\n@keyframes rotation {\n 0% {\n transform: rotate(0deg);\n }\n\n 100% {\n transform: rotate(360deg);\n }\n} \n\n/* END LOADING SPINNER */\n\n.transcodate-form-container {\n\tmargin-top: 20px;\n\tdisplay: flex;\n\tflex-wrap: wrap;\n flex-direction: row;\n gap: 10px;\n}\n\n.transcodate-form-container > .form-control {\n\tdisplay: flex;\n\tflex-wrap: nowrap;\n flex-direction: row;\n justify-content: flex-start;\n gap: 10px;\n align-items: center;\n}\n\n.transcodate-form-container > .form-control > strong {\n\twhite-space: nowrap;\n\tdisplay: inline-block;\n width: 100px;\n}\n\n.crf-range {\n margin-left: 5px;\n}\n\n#progress {\n margin-top: 20px;\n margin-bottom: 0;\n}\n\n.progress-circle {\n/* transform: rotate(-90deg);*/\n}\n\n.circle-bg {\n stroke-dasharray: 100, 100;\n}\n\n.circle-progress {\n transition: stroke-dasharray 0.3s ease;\n}\n\n.list-group-item.task {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n}\n\n.list-group-item.task .file {\n display: flex;\n flex-direction: row;\n gap: 8px;\n align-items: center;\n}\n\n.sm-spinner {\n width: 18px;\n height: 18px;\n border-width: 3px;\n} \n\n.btn {\n .border-spinner {\n margin-right: 2px;\n position: relative;\n top: 1px;\n }\n\n &.inprogress {\n display: inline-flex;\n gap: 6px;\n align-items: center;\n }\n}",".component.media-list {\n\t.do-rescan-media-lib {\n\t\t.spinner-border {\n\t\t\tdisplay: none;\n\t\t}\n\n\t\t&.inprogress {\n\t\t\t.spinner-border {\n\t\t\t\tdisplay: block;\n\t\t\t}\n\t\t}\n\t}\n}"]} \ No newline at end of file diff --git a/static/js/components/media-list.js b/static/js/components/media-list.js index ba880df..778f1f7 100644 --- a/static/js/components/media-list.js +++ b/static/js/components/media-list.js @@ -36,8 +36,14 @@ function rescanMediaLibHandler() { $("#do-rescan-media-lib").on("click", function(){ + if($(this).hasClass("disabled")) { + return; + } + + console.log('test'); $.getJSON("/media-list/clear-cache").done(function(resp){ if(resp.status) { + document.getElementById("do-rescan-media-lib").setStateInprogress(); return; // $('#media-table').DataTable().destroy(); // return loadMediaList(); @@ -53,6 +59,10 @@ function renderMediaList(data) { const tableBody = $("#media-table tbody"); + if(typeof data != "object") { + return; + } + if (data.length > 0) { data.forEach((file, index) => { const videoInfo = file.info.video @@ -115,9 +125,41 @@ }); } +let lastMediaLibScaningProcessMsg = ""; + +function initScaningProcessingView() { + const activateBtn = document.getElementById("do-rescan-media-lib"); + activateBtn.setStateInprogress = () => { + changeBtnStateToInProgress(activateBtn); + } + + activateBtn.setStateDefault = () => { + changeBtnStateToDefault(activateBtn); + } + + + const scaningProcessingContainer = $(".scaning-process-container"); + + socket.on("medialib-scaning-process", data => { + if(!scaningProcessingContainer.is(":visible")) { + scaningProcessingContainer.html(""); + scaningProcessingContainer.slideDown(); + activateBtn.setStateInprogress(); + } + + if(lastMediaLibScaningProcessMsg == data.message) { + return; + } + + lastMediaLibScaningProcessMsg = data.message; + scaningProcessingContainer.html(data.message); + }); +} + $(document).ready(function() { loadMediaList(); rescanMediaLibHandler(); + initScaningProcessingView(); socket.on("medialib-scaning-complete", resp => { if($('#media-table_wrapper').length) { @@ -126,5 +168,8 @@ } renderMediaList(resp.data); + + $(".scaning-process-container").slideUp(); + document.getElementById("do-rescan-media-lib").setStateDefault(); }); }); \ No newline at end of file diff --git a/static/js/lib.js b/static/js/lib.js index 30f2df2..9d91ddb 100644 --- a/static/js/lib.js +++ b/static/js/lib.js @@ -15,4 +15,24 @@ function calcTranscodingProgress(time, duration) { return Math.floor(timeToSeconds(time) / parseInt(duration) * 100); +} + +function changeBtnStateToInProgress(btn) { + if(btn.stateIsInprogress) { + return; + } + + btn.stateIsInprogress = true; + $(btn).addClass("inprogress"); + $(btn).addClass("disabled"); +} + +function changeBtnStateToDefault(btn) { + if(!btn.stateIsInprogress) { + return; + } + + btn.stateIsInprogress = false; + $(btn).removeClass("inprogress"); + $(btn).removeClass("disabled"); } \ No newline at end of file diff --git a/templates/components/media-list.html b/templates/components/media-list.html index 7b09573..22b3c7b 100644 --- a/templates/components/media-list.html +++ b/templates/components/media-list.html @@ -1,23 +1,30 @@ -
- Configure Directories - -
+
+
+ Configure Directories + +
-
- -
+ - - - - - - - - - - - -
#FileSize
+
+ +
+ + + + + + + + + + + + +
#FileSize
+
\ No newline at end of file