diff --git a/assets/release_notes.md b/assets/release_notes.md index f50934b4..f38d8413 100644 --- a/assets/release_notes.md +++ b/assets/release_notes.md @@ -1,3 +1,8 @@ +## 0.22.1 - February 2026 +--- + +- Fixes bug related to fetching images from remote URLs + ### 0.22.0 - February 2026 --- diff --git a/lib/api.dart b/lib/api.dart index c4f6e8fc..e3b7d16e 100644 --- a/lib/api.dart +++ b/lib/api.dart @@ -213,30 +213,27 @@ class InvenTreeAPI { return url; } - String _makeUrl(String url) { - // Strip leading slash - if (url.startsWith("/")) { - url = url.substring(1, url.length); + // Resolve a relative or absolute URL + String _makeUrl(String url, {String base = ""}) { + final baseUri = Uri.parse(base.isNotEmpty ? base : baseUrl); + final pathUri = Uri.parse(url); + + // If path is absolute (has scheme), ignore base + if (pathUri.hasScheme) { + return pathUri.toString(); } - // Prevent double-slash - url = url.replaceAll("//", "/"); - - return baseUrl + url; + return baseUri.resolveUri(pathUri).toString(); } - String get apiUrl => _makeUrl("/api/"); - - String get imageUrl => _makeUrl("/image/"); - String makeApiUrl(String endpoint) { - if (endpoint.startsWith("/api/") || endpoint.startsWith("api/")) { - return _makeUrl(endpoint); - } else { - return _makeUrl("/api/${endpoint}"); - } + String apiBase = makeUrl("/api/"); + + return _makeUrl(endpoint, base: apiBase); } + String get apiUrl => makeApiUrl(""); + String makeUrl(String endpoint) => _makeUrl(endpoint); UserProfile? profile; @@ -1143,7 +1140,7 @@ class InvenTreeAPI { * Perform a request to link a custom barcode to a particular item */ Future linkBarcode(Map body) async { - HttpClientRequest? request = await apiRequest("/barcode/link/", "POST"); + HttpClientRequest? request = await apiRequest("barcode/link/", "POST"); if (request == null) { return false; @@ -1162,7 +1159,7 @@ class InvenTreeAPI { * Perform a request to unlink a custom barcode from a particular item */ Future unlinkBarcode(Map body) async { - HttpClientRequest? request = await apiRequest("/barcode/unlink/", "POST"); + HttpClientRequest? request = await apiRequest("barcode/unlink/", "POST"); if (request == null) { return false; diff --git a/lib/inventree/stock.dart b/lib/inventree/stock.dart index 657a2181..8ff680a1 100644 --- a/lib/inventree/stock.dart +++ b/lib/inventree/stock.dart @@ -534,19 +534,19 @@ class InvenTreeStockItem extends InvenTreeModel { } Future countStock(double q, {String? notes}) async { - final bool result = await adjustStock("/stock/count/", q, notes: notes); + final bool result = await adjustStock("stock/count/", q, notes: notes); return result; } Future addStock(double q, {String? notes}) async { - final bool result = await adjustStock("/stock/add/", q, notes: notes); + final bool result = await adjustStock("stock/add/", q, notes: notes); return result; } Future removeStock(double q, {String? notes}) async { - final bool result = await adjustStock("/stock/remove/", q, notes: notes); + final bool result = await adjustStock("stock/remove/", q, notes: notes); return result; } @@ -563,7 +563,7 @@ class InvenTreeStockItem extends InvenTreeModel { } final bool result = await adjustStock( - "/stock/transfer/", + "stock/transfer/", q, notes: notes, location: location, diff --git a/pubspec.yaml b/pubspec.yaml index 4c535d28..14f931f7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: inventree description: InvenTree stock management -version: 0.22.0+109 +version: 0.22.1+110 environment: sdk: ^3.8.1 diff --git a/test/api_test.dart b/test/api_test.dart index f19dbf41..3bd5cdb1 100644 --- a/test/api_test.dart +++ b/test/api_test.dart @@ -23,6 +23,27 @@ void main() { assert(await UserProfileDBManager().selectProfileByName(testServerName)); }); + // Ensure that generated URLs are correct + group("URL Tests:", () { + test("Generate URLs", () async { + UserProfile profile = await setupServerProfile(); + var api = InvenTreeAPI(); + + api.profile = profile; + + Map tests = { + "": "http://localhost:8000/api/", + "barcode/": "http://localhost:8000/api/barcode/", + "https://remote-server.com/media/image.png": + "https://remote-server.com/media/image.png", + }; + + for (var test in tests.entries) { + expect(api.makeApiUrl(test.key), equals(test.value)); + } + }); + }); + group("Login Tests:", () { test("Disconnected", () async { // Test that calling disconnect() does the right thing