From f7ce255160895cca4ebba98c5d0f1da58d2e338f Mon Sep 17 00:00:00 2001
From: Stephan Sundermann <stephansundermann@gmail.com>
Date: Sat, 14 Dec 2024 19:55:09 +0100
Subject: [PATCH 1/3] Use file browser dialog for local path

---
 jellyfin_kodi/helper/utils.py | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/jellyfin_kodi/helper/utils.py b/jellyfin_kodi/helper/utils.py
index 4a7857b9..d3d780d8 100644
--- a/jellyfin_kodi/helper/utils.py
+++ b/jellyfin_kodi/helper/utils.py
@@ -10,7 +10,7 @@ import sys
 import re
 import unicodedata
 from uuid import uuid4
-from urllib.parse import quote_plus
+from urllib.parse import quote_plus, urlparse, urlunparse
 
 from dateutil import tz, parser
 
@@ -157,6 +157,7 @@ def dialog(dialog_type, *args, **kwargs):
         "select": d.select,
         "numeric": d.numeric,
         "multi": d.multiselect,
+        "browse": d.browse,
     }
     return types[dialog_type](*args, **kwargs)
 
@@ -487,6 +488,13 @@ def set_addon_mode():
     LOG.info("Add-on playback: %s", settings("useDirectPaths") == "0")
 
 
+def strip_credentials(url):
+    parsed = urlparse(url)
+    netloc = parsed.netloc.split("@")[-1]  # Remove credentials
+    stripped_url = urlunparse(parsed._replace(netloc=netloc))
+    return stripped_url
+
+
 def path_replacements():
     # UI to display and manage path replacements for native mode
     from ..database import get_credentials, save_credentials
@@ -509,7 +517,9 @@ def path_replacements():
         if selected_path == 1:
             # Add a new path replacement
             remote_path = dialog("input", translate(33206))
-            local_path = dialog("input", translate(33207))
+            local_path = strip_credentials(
+                dialog("browse", type=0, heading=translate(33207), shares="")
+            )
             if remote_path and local_path:
                 paths[remote_path] = local_path
         elif selected_path > 1:
@@ -520,7 +530,15 @@ def path_replacements():
             del paths[edit_remote_path]
             # Prepopulate the text box with the existing value
             remote_path = dialog("input", translate(33206), defaultt=edit_remote_path)
-            local_path = dialog("input", translate(33207), defaultt=edit_local_path)
+            local_path = strip_credentials(
+                dialog(
+                    "browse",
+                    type=0,
+                    heading=translate(33207),
+                    shares="",
+                    defaultt=edit_local_path,
+                )
+            )
             if remote_path and local_path:
                 paths[remote_path] = local_path
 

From cfc532377ea86c270878f915bb79013ff698d37f Mon Sep 17 00:00:00 2001
From: Stephan Sundermann <stephansundermann@gmail.com>
Date: Mon, 16 Dec 2024 03:09:45 +0100
Subject: [PATCH 2/3] Add tests for strip_credentials

---
 tests/test_helper_utils.py | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/tests/test_helper_utils.py b/tests/test_helper_utils.py
index 145e8114..e571c337 100644
--- a/tests/test_helper_utils.py
+++ b/tests/test_helper_utils.py
@@ -15,7 +15,7 @@ else:
 
 import pytest
 
-from jellyfin_kodi.helper.utils import values, convert_to_local
+from jellyfin_kodi.helper.utils import values, convert_to_local, strip_credentials
 
 item1 = {"foo": 123, "bar": 456, "baz": 789}
 
@@ -77,3 +77,23 @@ def test_values(item, keys, expected):
 )
 def test_convert_to_local(utctime, timezone, expected):
     assert convert_to_local(utctime, timezone=zoneinfo.ZoneInfo(timezone)) == expected
+
+@pytest.mark.parametrize(
+    "url,expected",
+    [
+        ("smb://user:pass@server.test/media", "smb://server.test/media"),
+        ("smb://server.test/media", "smb://server.test/media"),
+        ("smb://user:pass@192.0.2.1/media", "smb://192.0.2.1/media"),
+        ("smb://user@192.0.2.1/media", "smb://192.0.2.1/media"),
+        ("nfs://server.test/media", "nfs://server.test/media"),
+        ("sftp://user:pass@server.test/media", "sftp://server.test/media"),
+        ("file://media/movies", "file://media/movies"),
+        ("/media/movies", "/media/movies"),
+        ("http://user:pass@server.test/media", "http://server.test/media"),
+        ("https://user:pass@server.test/media", "https://server.test/media"),
+        ("http://server.test/media", "http://server.test/media"),
+        ("https://server.test/media", "https://server.test/media"),
+    ],
+)
+def test_strip_credentials(url, expected):
+    assert strip_credentials(url) == expected

From 6c1dfeb4def71445e881d927e41a635ae8d27228 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Odd=20Str=C3=A5b=C3=B8?= <oddstr13@openshell.no>
Date: Sat, 21 Dec 2024 02:44:11 +0100
Subject: [PATCH 3/3] Update tests/test_helper_utils.py

---
 tests/test_helper_utils.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/test_helper_utils.py b/tests/test_helper_utils.py
index e571c337..7cb7c94b 100644
--- a/tests/test_helper_utils.py
+++ b/tests/test_helper_utils.py
@@ -78,6 +78,7 @@ def test_values(item, keys, expected):
 def test_convert_to_local(utctime, timezone, expected):
     assert convert_to_local(utctime, timezone=zoneinfo.ZoneInfo(timezone)) == expected
 
+
 @pytest.mark.parametrize(
     "url,expected",
     [