mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-01-11 22:40:31 +00:00
Merge d5bca753de into da675cd56c
This commit is contained in:
commit
47dc044163
1 changed files with 112 additions and 1 deletions
|
|
@ -11,6 +11,7 @@ const SearchParamsHandler = () => {
|
|||
const toast = useToast();
|
||||
|
||||
const [searchParams, setSearchParams] = React.useState({});
|
||||
const processedAddonsCollectionRef = React.useRef(null);
|
||||
|
||||
const onLocationChange = () => {
|
||||
const { origin, hash, search } = window.location;
|
||||
|
|
@ -23,7 +24,7 @@ const SearchParamsHandler = () => {
|
|||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
const { streamingServerUrl } = searchParams;
|
||||
const { streamingServerUrl, addonsCollection } = searchParams;
|
||||
|
||||
if (streamingServerUrl) {
|
||||
core.transport.dispatch({
|
||||
|
|
@ -49,6 +50,116 @@ const SearchParamsHandler = () => {
|
|||
timeout: 4000,
|
||||
});
|
||||
}
|
||||
|
||||
// Handle custom add-ons collection for new users and guests
|
||||
// This allows distributing pre-configured add-on bundles via URL parameter
|
||||
// Example: ?addonsCollection=https://example.com/addons.json
|
||||
if (addonsCollection && typeof addonsCollection === 'string' && addonsCollection.length > 0) {
|
||||
// Processing this collection only once per session
|
||||
if (processedAddonsCollectionRef.current === addonsCollection) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isNewUserOrGuest = !profile?.auth || profile?.auth?.user?.isNewUser === true;
|
||||
|
||||
if (isNewUserOrGuest) {
|
||||
processedAddonsCollectionRef.current = addonsCollection;
|
||||
fetch(addonsCollection)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch add-ons collection: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then((collectionData) => {
|
||||
// Install each add-on from the collection
|
||||
if (Array.isArray(collectionData)) {
|
||||
// For each entry, ensuring that the Core with a proper `manifest` object.
|
||||
const installPromises = collectionData.map((addon) => {
|
||||
return new Promise((resolve) => {
|
||||
(async () => {
|
||||
try {
|
||||
// Helper to dispatch InstallAddon with manifest object
|
||||
const doDispatch = (manifestObj, transportUrl, name) => {
|
||||
const args = {};
|
||||
if (manifestObj) args.manifest = manifestObj;
|
||||
if (transportUrl) args.transportUrl = transportUrl;
|
||||
if (name) args.name = name;
|
||||
if (Object.keys(args).length > 0) {
|
||||
core.transport.dispatch({
|
||||
action: 'Ctx',
|
||||
args: {
|
||||
action: 'InstallAddon',
|
||||
args,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof addon === 'string') {
|
||||
// treat as manifest URL: fetch and parse
|
||||
const manifestUrl = addon;
|
||||
try {
|
||||
const res = await fetch(manifestUrl);
|
||||
if (!res.ok) throw new Error(`Failed to fetch manifest: ${res.statusText}`);
|
||||
const manifestObj = await res.json();
|
||||
doDispatch(manifestObj, manifestUrl, null);
|
||||
} catch (e) {
|
||||
console.error('Failed to fetch/parse manifest for', manifestUrl, e);
|
||||
}
|
||||
} else if (addon && typeof addon === 'object') {
|
||||
// addon may contain manifest as object or URL
|
||||
const name = typeof addon.name === 'string' ? addon.name : null;
|
||||
if (addon.manifest && typeof addon.manifest === 'object') {
|
||||
|
||||
doDispatch(addon.manifest, addon.transportUrl || null, name);
|
||||
} else {
|
||||
// manifest field might be a URL, or fallback to transportUrl/url
|
||||
const manifestUrl = addon.manifest || addon.transportUrl || addon.url || null;
|
||||
if (manifestUrl && typeof manifestUrl === 'string') {
|
||||
try {
|
||||
const res = await fetch(manifestUrl);
|
||||
if (!res.ok) throw new Error(`Failed to fetch manifest: ${res.statusText}`);
|
||||
const manifestObj = await res.json();
|
||||
doDispatch(manifestObj, addon.transportUrl || manifestUrl, name);
|
||||
} catch (e) {
|
||||
console.error('Failed to fetch/parse manifest for', manifestUrl, e);
|
||||
}
|
||||
} else {
|
||||
console.warn('Skipping invalid add-on entry in collection:', addon);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.warn('Skipping invalid add-on entry in collection:', addon);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error processing add-on entry:', addon, e);
|
||||
} finally {
|
||||
resolve();
|
||||
}
|
||||
})();
|
||||
});
|
||||
});
|
||||
|
||||
Promise.all(installPromises).then(() => {
|
||||
toast.show({
|
||||
type: 'success',
|
||||
title: `Processed ${collectionData.length} add-on entries from collection`,
|
||||
timeout: 4000,
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed to load add-ons collection:', error);
|
||||
toast.show({
|
||||
type: 'error',
|
||||
title: 'Failed to load add-ons collection',
|
||||
timeout: 4000,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [searchParams]);
|
||||
|
||||
React.useEffect(() => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue