mirror of
https://github.com/ranaldsgift/KefinTweaks.git
synced 2026-11-05 15:52:47 +01:00
Add support for native Grouped library and Exclude library from Latest/Resume sections, and add Peacock and Hulu to browse by studio section
This commit is contained in:
@@ -699,7 +699,7 @@
|
||||
{ name: 'Dreamworks Animation', file: 'DreamWorks_Animation.svg' },
|
||||
{ name: 'FX', file: 'FX.svg' },
|
||||
{ name: 'HBO', file: 'HBO.svg' },
|
||||
{ name: 'Lucasfilm', file: 'Lucasfilm.svg' },
|
||||
{ name: 'Lucasfilm Ltd.', file: 'Lucasfilm.svg' },
|
||||
{ name: 'Marvel Studios', file: 'Marvel_Studios.svg' },
|
||||
{ name: 'New Line Cinema', file: 'New_Line_Cinema.svg' },
|
||||
{ name: 'Paramount Pictures', file: 'Paramount_Pictures.svg' },
|
||||
@@ -709,13 +709,44 @@
|
||||
{ name: 'Walt Disney Pictures', file: 'Walt_Disney_Pictures.svg' },
|
||||
{ name: 'Warner Bros.', file: 'Warner_Bros..svg' },
|
||||
{ name: 'HBO Max', file: 'HBO_Max.svg' },
|
||||
{ name: 'Prime Video', file: 'Prime_Video.svg' }
|
||||
{ name: 'Prime Video', file: 'Prime_Video.svg' },
|
||||
{ name: 'Hulu', file: 'Hulu.svg' },
|
||||
{ name: 'Peacock', file: 'Peacock.svg' }
|
||||
];
|
||||
|
||||
const BROWSE_BY_STUDIO_SECTION_ID = 'browse-by-studio';
|
||||
const BROWSE_BY_STUDIO_GROUP_ID = 'home-popular-studios';
|
||||
const BROWSE_BY_STUDIO_GROUP_NAME = 'Popular Studios';
|
||||
|
||||
const RECENTLY_ADDED_GROUPED_MOVIES_ID = 'recently-added-grouped-movies';
|
||||
const RECENTLY_ADDED_GROUPED_TVSHOWS_ID = 'recently-added-grouped-tvshows';
|
||||
const RECENTLY_ADDED_GROUPED_SHELL_IDS = new Set([
|
||||
RECENTLY_ADDED_GROUPED_MOVIES_ID,
|
||||
RECENTLY_ADDED_GROUPED_TVSHOWS_ID
|
||||
]);
|
||||
|
||||
function buildGroupedRecentlyAddedShell(collectionType) {
|
||||
const isMovies = collectionType === 'movies';
|
||||
return {
|
||||
id: isMovies ? RECENTLY_ADDED_GROUPED_MOVIES_ID : RECENTLY_ADDED_GROUPED_TVSHOWS_ID,
|
||||
name: isMovies ? 'Recently Added Movies' : 'Recently Added TV Shows',
|
||||
enabled: false,
|
||||
order: 61,
|
||||
cardFormat: 'Poster',
|
||||
jellyfinId: 'latestmedia',
|
||||
userConfigurable: true,
|
||||
queries: [{
|
||||
path: '/Items/Latest',
|
||||
queryOptions: {
|
||||
Fields: 'PrimaryImageAspectRatio,Path',
|
||||
Limit: 16,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: 'Primary,Backdrop,Thumb'
|
||||
}
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
let browseStudiosFetchPromise = null;
|
||||
|
||||
function isBrowseByStudioCatalogFullyResolved(existingItems) {
|
||||
@@ -937,6 +968,9 @@
|
||||
|
||||
const sectionsToRemove = groupSections.filter(s => {
|
||||
if (!s.id || !s.id.startsWith(template.idPrefix)) return false;
|
||||
if (template.idPrefix === 'recently-added-' && RECENTLY_ADDED_GROUPED_SHELL_IDS.has(s.id)) {
|
||||
return false;
|
||||
}
|
||||
const libId = s.id.replace(template.idPrefix, '');
|
||||
return !currentLibraryIds.has(libId);
|
||||
});
|
||||
@@ -961,11 +995,42 @@
|
||||
});
|
||||
}
|
||||
|
||||
// Style-only grouped Movies/TV shells when multiple libraries of that type exist
|
||||
{
|
||||
const recentlyAddedGroup = updatedGroups.find(
|
||||
(g) => g.id === 'home-recently-added' || g.name === 'Recently Added'
|
||||
);
|
||||
if (recentlyAddedGroup) {
|
||||
if (!Array.isArray(recentlyAddedGroup.sections)) {
|
||||
recentlyAddedGroup.sections = [];
|
||||
}
|
||||
const movieCount = filteredLibraries.filter((l) => l.CollectionType === 'movies').length;
|
||||
const tvCount = filteredLibraries.filter((l) => l.CollectionType === 'tvshows').length;
|
||||
const shellSpecs = [
|
||||
{ id: RECENTLY_ADDED_GROUPED_MOVIES_ID, want: movieCount > 1, collectionType: 'movies' },
|
||||
{ id: RECENTLY_ADDED_GROUPED_TVSHOWS_ID, want: tvCount > 1, collectionType: 'tvshows' }
|
||||
];
|
||||
for (const spec of shellSpecs) {
|
||||
const idx = recentlyAddedGroup.sections.findIndex((s) => s?.id === spec.id);
|
||||
if (spec.want && idx === -1) {
|
||||
recentlyAddedGroup.sections.push(buildGroupedRecentlyAddedShell(spec.collectionType));
|
||||
hasChanges = true;
|
||||
LOG(`Added grouped recently-added shell: ${spec.id}`);
|
||||
} else if (!spec.want && idx !== -1) {
|
||||
recentlyAddedGroup.sections.splice(idx, 1);
|
||||
hasChanges = true;
|
||||
LOG(`Removed grouped recently-added shell: ${spec.id}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove stale library sections from any HOME group (e.g. misplaced sections)
|
||||
for (const group of updatedGroups) {
|
||||
const beforeCount = (group.sections || []).length;
|
||||
group.sections = (group.sections || []).filter(s => {
|
||||
if (!s?.id) return true;
|
||||
if (RECENTLY_ADDED_GROUPED_SHELL_IDS.has(s.id)) return true;
|
||||
for (const template of libraryTemplates) {
|
||||
if (s.id.startsWith(template.idPrefix)) {
|
||||
const libId = s.id.replace(template.idPrefix, '');
|
||||
@@ -1002,6 +1067,20 @@
|
||||
}
|
||||
|
||||
const browseSection = studiosGroup.sections.find((s) => s?.id === BROWSE_BY_STUDIO_SECTION_ID);
|
||||
const catalogNames = new Set(BROWSE_BY_STUDIO_CATALOG.map((entry) => entry.name));
|
||||
|
||||
// Prune items no longer in Kefin catalog (even when catalog is otherwise fully resolved)
|
||||
if (browseSection && Array.isArray(browseSection.items)) {
|
||||
const beforeLen = browseSection.items.length;
|
||||
browseSection.items = browseSection.items.filter(
|
||||
(item) => item?.Name && catalogNames.has(item.Name)
|
||||
);
|
||||
if (browseSection.items.length !== beforeLen) {
|
||||
hasChanges = true;
|
||||
LOG(`Pruned ${beforeLen - browseSection.items.length} browse-by-studio studios not in catalog`);
|
||||
}
|
||||
}
|
||||
|
||||
const existingItems = Array.isArray(browseSection?.items) ? browseSection.items : [];
|
||||
|
||||
if (browseSection && isBrowseByStudioCatalogFullyResolved(existingItems)) {
|
||||
@@ -1070,10 +1149,15 @@
|
||||
|
||||
const KEFIN_DEFAULT_GROUP_KEYS = ['HOME_SECTION_GROUPS', 'SEASONAL_SECTION_GROUPS', 'DISCOVERY_SECTION_GROUPS'];
|
||||
const LIBRARY_RESOLVED_ID_PREFIXES = ['recently-added-', 'popular-genres-'];
|
||||
const FIXED_TEMPLATE_SECTION_IDS = new Set([BROWSE_BY_STUDIO_SECTION_ID]);
|
||||
const FIXED_TEMPLATE_SECTION_IDS = new Set([
|
||||
BROWSE_BY_STUDIO_SECTION_ID,
|
||||
RECENTLY_ADDED_GROUPED_MOVIES_ID,
|
||||
RECENTLY_ADDED_GROUPED_TVSHOWS_ID
|
||||
]);
|
||||
|
||||
function isLibraryResolvedSectionId(sectionId) {
|
||||
if (!sectionId) return false;
|
||||
if (RECENTLY_ADDED_GROUPED_SHELL_IDS.has(sectionId)) return true;
|
||||
return LIBRARY_RESOLVED_ID_PREFIXES.some((prefix) => sectionId.startsWith(prefix));
|
||||
}
|
||||
|
||||
|
||||
@@ -908,6 +908,235 @@
|
||||
return catalog.filter((s) => resolveSectionJellyfinId(s) === type);
|
||||
}
|
||||
|
||||
const RECENTLY_ADDED_PREFIX = 'recently-added-';
|
||||
const RECENTLY_ADDED_GROUPED_MOVIES_ID = 'recently-added-grouped-movies';
|
||||
const RECENTLY_ADDED_GROUPED_TVSHOWS_ID = 'recently-added-grouped-tvshows';
|
||||
const LATEST_EXCLUDE_VIEW_TYPES = new Set(['playlists', 'livetv', 'boxsets', 'channels', 'folders']);
|
||||
|
||||
function isRecentlyAddedGroupedShellId(id) {
|
||||
return id === RECENTLY_ADDED_GROUPED_MOVIES_ID || id === RECENTLY_ADDED_GROUPED_TVSHOWS_ID;
|
||||
}
|
||||
|
||||
function cloneRecentlyAddedSection(section) {
|
||||
const next = { ...section };
|
||||
if (Array.isArray(section.queries)) {
|
||||
next.queries = section.queries.map((q) => ({
|
||||
...q,
|
||||
queryOptions: q?.queryOptions ? { ...q.queryOptions } : {}
|
||||
}));
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
function applyHidePlayedInLatestToSection(section) {
|
||||
if (!Array.isArray(section.queries)) return section;
|
||||
section.queries = section.queries.map((q) => ({
|
||||
...q,
|
||||
queryOptions: {
|
||||
...(q.queryOptions || {}),
|
||||
IsPlayed: false
|
||||
}
|
||||
}));
|
||||
return section;
|
||||
}
|
||||
|
||||
function buildMinimalGroupedRecentlyAddedShell(collectionType) {
|
||||
const isMovies = collectionType === 'movies';
|
||||
return {
|
||||
id: isMovies ? RECENTLY_ADDED_GROUPED_MOVIES_ID : RECENTLY_ADDED_GROUPED_TVSHOWS_ID,
|
||||
name: isMovies ? 'Recently Added Movies' : 'Recently Added TV Shows',
|
||||
enabled: false,
|
||||
order: 61,
|
||||
cardFormat: 'Poster',
|
||||
jellyfinId: 'latestmedia',
|
||||
userConfigurable: true,
|
||||
queries: [{
|
||||
path: '/Items/Latest',
|
||||
queryOptions: {
|
||||
Fields: 'PrimaryImageAspectRatio,Path',
|
||||
Limit: 16,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: 'Primary,Backdrop,Thumb'
|
||||
}
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-library recently-added rows folded into a combined Movies/TV UserView
|
||||
* (library Id no longer appears in eligible UserViews).
|
||||
*/
|
||||
function collectFoldedRecentlyAddedByType(sections, eligibleViewIds, libTypeById) {
|
||||
const folded = { movies: [], tvshows: [] };
|
||||
(sections || []).forEach((section) => {
|
||||
const id = String(section?.id || '');
|
||||
if (!id.startsWith(RECENTLY_ADDED_PREFIX) || isRecentlyAddedGroupedShellId(id)) return;
|
||||
const libId = id.slice(RECENTLY_ADDED_PREFIX.length);
|
||||
if (eligibleViewIds.has(libId)) return;
|
||||
const ct = String(libTypeById.get(libId) || '').toLowerCase();
|
||||
if (ct === 'movies' || ct === 'tvshows') {
|
||||
folded[ct].push(section);
|
||||
}
|
||||
});
|
||||
return folded;
|
||||
}
|
||||
|
||||
/** Default grouped enabled = true if any merged per-lib recently-added source is enabled. */
|
||||
function applyGroupedEnabledFromMergedSources(groupedSection, foldedSources) {
|
||||
const sources = foldedSources || [];
|
||||
if (!sources.length) return groupedSection;
|
||||
groupedSection.enabled = sources.some((s) => s?.enabled === true);
|
||||
return groupedSection;
|
||||
}
|
||||
|
||||
async function fetchUserViewsItems() {
|
||||
if (!window.ApiClient?.getCurrentUserId) return [];
|
||||
const userId = window.ApiClient.getCurrentUserId();
|
||||
if (window.ApiClient.getUserViews) {
|
||||
const result = await window.ApiClient.getUserViews({}, userId);
|
||||
if (Array.isArray(result)) return result;
|
||||
return result?.Items || [];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Reshape recently-added-* for the viewing user to match native Latest:
|
||||
* UserViews membership, LatestItemsExcludes, grouped Movies/TV shells, HidePlayedInLatest.
|
||||
* Returns in-memory clones only — does not persist queryOptions.
|
||||
*/
|
||||
async function resolveRecentlyAddedSectionsForUser(sections) {
|
||||
const list = Array.isArray(sections) ? sections : [];
|
||||
let user = null;
|
||||
try {
|
||||
user = await window.ApiClient?.getCurrentUser?.();
|
||||
} catch (e) {
|
||||
WARN('getCurrentUser failed during recently-added reshape:', e);
|
||||
}
|
||||
|
||||
const hidePlayed = user?.Configuration?.HidePlayedInLatest === true;
|
||||
const excludes = new Set(
|
||||
(user?.Configuration?.LatestItemsExcludes || []).map((id) => String(id))
|
||||
);
|
||||
|
||||
let userViews = [];
|
||||
try {
|
||||
userViews = await fetchUserViewsItems();
|
||||
} catch (e) {
|
||||
WARN('UserViews unavailable; applying HidePlayedInLatest only:', e);
|
||||
if (!hidePlayed) return list;
|
||||
return list.map((section) => {
|
||||
if (!String(section?.id || '').startsWith(RECENTLY_ADDED_PREFIX)) return section;
|
||||
return applyHidePlayedInLatestToSection(cloneRecentlyAddedSection(section));
|
||||
});
|
||||
}
|
||||
|
||||
const physicalLibraryIds = new Set();
|
||||
const libTypeById = new Map();
|
||||
try {
|
||||
if (window.dataHelper?.getLibraries) {
|
||||
const libs = await window.dataHelper.getLibraries();
|
||||
(libs || []).forEach((lib) => {
|
||||
if (lib?.Id) {
|
||||
physicalLibraryIds.add(String(lib.Id));
|
||||
libTypeById.set(String(lib.Id), String(lib.CollectionType || '').toLowerCase());
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (_) { /* fall through */ }
|
||||
if (physicalLibraryIds.size === 0) {
|
||||
list.forEach((section) => {
|
||||
const id = String(section?.id || '');
|
||||
if (!id.startsWith(RECENTLY_ADDED_PREFIX) || isRecentlyAddedGroupedShellId(id)) return;
|
||||
physicalLibraryIds.add(id.slice(RECENTLY_ADDED_PREFIX.length));
|
||||
});
|
||||
}
|
||||
|
||||
const eligibleViews = (userViews || []).filter((view) => {
|
||||
if (!view?.Id) return false;
|
||||
if (excludes.has(String(view.Id))) return false;
|
||||
const ct = String(view.CollectionType || '').toLowerCase();
|
||||
if (ct && LATEST_EXCLUDE_VIEW_TYPES.has(ct)) return false;
|
||||
return true;
|
||||
});
|
||||
const eligibleViewIds = new Set(eligibleViews.map((view) => String(view.Id)));
|
||||
|
||||
const combinedByType = new Map();
|
||||
eligibleViews.forEach((view) => {
|
||||
const ct = String(view.CollectionType || '').toLowerCase();
|
||||
if ((ct === 'movies' || ct === 'tvshows') && !physicalLibraryIds.has(String(view.Id))) {
|
||||
combinedByType.set(ct, view);
|
||||
}
|
||||
});
|
||||
|
||||
const foldedByType = collectFoldedRecentlyAddedByType(list, eligibleViewIds, libTypeById);
|
||||
|
||||
const sectionById = new Map();
|
||||
list.forEach((section) => {
|
||||
if (section?.id) sectionById.set(section.id, section);
|
||||
});
|
||||
|
||||
const result = [];
|
||||
let emittedGroupedMovies = false;
|
||||
let emittedGroupedTv = false;
|
||||
|
||||
function bindGroupedShell(ct, view, template) {
|
||||
const shellId = ct === 'movies' ? RECENTLY_ADDED_GROUPED_MOVIES_ID : RECENTLY_ADDED_GROUPED_TVSHOWS_ID;
|
||||
const next = cloneRecentlyAddedSection(template || buildMinimalGroupedRecentlyAddedShell(ct));
|
||||
next.id = shellId;
|
||||
if (view.Name) next.name = `Recently Added ${view.Name}`;
|
||||
if (Array.isArray(next.queries)) {
|
||||
next.queries = next.queries.map((q) => ({
|
||||
...q,
|
||||
queryOptions: {
|
||||
...(q.queryOptions || {}),
|
||||
ParentId: view.Id
|
||||
}
|
||||
}));
|
||||
}
|
||||
applyGroupedEnabledFromMergedSources(next, foldedByType[ct]);
|
||||
if (hidePlayed) applyHidePlayedInLatestToSection(next);
|
||||
return next;
|
||||
}
|
||||
|
||||
for (const section of list) {
|
||||
const id = String(section?.id || '');
|
||||
if (!id.startsWith(RECENTLY_ADDED_PREFIX)) {
|
||||
result.push(section);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id === RECENTLY_ADDED_GROUPED_MOVIES_ID || id === RECENTLY_ADDED_GROUPED_TVSHOWS_ID) {
|
||||
const ct = id === RECENTLY_ADDED_GROUPED_MOVIES_ID ? 'movies' : 'tvshows';
|
||||
const view = combinedByType.get(ct);
|
||||
if (!view) continue;
|
||||
const template = sectionById.get(id) || buildMinimalGroupedRecentlyAddedShell(ct);
|
||||
result.push(bindGroupedShell(ct, view, template));
|
||||
if (ct === 'movies') emittedGroupedMovies = true;
|
||||
else emittedGroupedTv = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
const libId = id.slice(RECENTLY_ADDED_PREFIX.length);
|
||||
if (!eligibleViewIds.has(libId)) continue;
|
||||
|
||||
const next = cloneRecentlyAddedSection(section);
|
||||
if (hidePlayed) applyHidePlayedInLatestToSection(next);
|
||||
result.push(next);
|
||||
}
|
||||
|
||||
// Combined view exists but admin shell was missing from catalog — append synthesized row
|
||||
for (const [ct, view] of combinedByType) {
|
||||
if (ct === 'movies' && emittedGroupedMovies) continue;
|
||||
if (ct === 'tvshows' && emittedGroupedTv) continue;
|
||||
const shellId = ct === 'movies' ? RECENTLY_ADDED_GROUPED_MOVIES_ID : RECENTLY_ADDED_GROUPED_TVSHOWS_ID;
|
||||
const template = sectionById.get(shellId) || buildMinimalGroupedRecentlyAddedShell(ct);
|
||||
result.push(bindGroupedShell(ct, view, template));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable Kefin sections from native Jellyfin homesectionN (enable-only, no order changes).
|
||||
* If any candidate for a native type is already enabled, skip that type.
|
||||
@@ -1036,6 +1265,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Align recently-added-* with native Latest (UserViews, excludes, grouped, HidePlayedInLatest)
|
||||
sections = await resolveRecentlyAddedSectionsForUser(sections);
|
||||
|
||||
sections = sections.filter((section) => section.enabled || section.userConfigurable === true || section.userConfigurable === undefined);
|
||||
sections = deduplicateHomeScreenSections(sections);
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 216 71.15">
|
||||
<g style="fill:#ffffff">
|
||||
<path d="M102.07,22.2c0,0,0,27.75,0,28.71c0,2.54-2.05,4.6-4.6,4.6H87.5c-2.54,0-4.6-2.06-4.6-4.6 c0-0.96,0-28.71,0-28.71H65.74v30.14c0,12.32,7.88,18.81,19.53,18.81H99.7c11.65,0,19.53-6.49,19.53-18.81V22.2H102.07z"/>
|
||||
<path d="M198.85,22.2c0,0,0,27.75,0,28.71c0,2.54-2.05,4.6-4.6,4.6h-9.98c-2.54,0-4.6-2.06-4.6-4.6 c0-0.96,0-28.71,0-28.71h-17.16v30.14c0,12.32,7.88,18.81,19.53,18.81h14.42c11.65,0,19.53-6.49,19.53-18.81V22.2H198.85z"/>
|
||||
<path d="M33.95,22.2c0,0-8.94,0-11,0c-3.86,0-5.8,1.04-5.8,1.04V0H0v71.15h17.15V42.44c0-2.54,2.06-4.6,4.6-4.6h9.98 c2.54,0,4.59,2.06,4.59,4.6v28.71l17.16,0V40.21C53.48,27.21,44.81,22.2,33.95,22.2z"/>
|
||||
<rect x="132.3" width="17.16" height="71.15"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 806 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" aria-hidden="true" data-testid="peacock-wob-logo" viewBox="0 0 1607 400"><g clip-path="url(#a)"><path fill="url(#b)" d="M1606.99 31.25c0 17.26-13.99 31.25-31.25 31.25s-31.25-13.99-31.25-31.25S1558.48 0 1575.74 0s31.25 13.99 31.25 31.25m-31.25 53.13c-17.26 0-31.25 13.99-31.25 31.25s13.99 31.25 31.25 31.25 31.25-13.99 31.25-31.25-13.99-31.25-31.25-31.25m0 84.37c-17.26 0-31.25 13.99-31.25 31.25s13.99 31.25 31.25 31.25 31.25-13.99 31.25-31.25-13.99-31.25-31.25-31.25m0 84.37c-17.26 0-31.25 13.99-31.25 31.25s13.99 31.25 31.25 31.25 31.25-13.99 31.25-31.25-13.99-31.25-31.25-31.25m0 84.38c-17.26 0-31.25 13.99-31.25 31.25s13.99 31.25 31.25 31.25 31.25-13.99 31.25-31.25-13.99-31.25-31.25-31.25"/><path fill="#fff" d="M1213.52 89.3501c15.38 0 29.97 3.16 43.38 9.86V155.6c-11.04-9.86-27.61-17.35-44.57-17.35-33.52 0-59.15 27.21-59.15 62.31s25.63 61.91 59.95 61.12c16.96 0 33.12-5.92 43.78-16.56v55.6c-14.2 6.31-28.79 10.65-44.57 10.65-61.92 0-112-49.69-112-110.81s51.27-111.1999 113.19-111.1999zM217.7 194.64c0 65.68-50.87 117.91-164.85 131.01v69.71H0v-195.2c0-69.8 49.3-110.8099 111.22-110.8099S217.7 135.49 217.7 194.64m-52.85 1.97c0-32.34-24.45-56.78-55.61-56.78s-56.4 22.08-56.4 60.33v75.28c42.33-1.2 112-24.91 112-78.83zm536.36 3.94c0 61.12 49.69 110.81 112 110.81 15.38 0 30.37-4.34 44.18-10.65v-55.6c-10.25 10.25-26.82 16.56-43.38 16.56-34.31.79-59.95-26.42-59.95-61.12s25.63-62.31 59.15-62.31c16.96 0 33.13 7.49 44.18 17.35V99.2001c-13.41-6.7-28-9.86-42.6-9.86-62.71 0-113.58 49.6899-113.58 111.1999zm780.88 104.5-91.82-108.36 81.57-101.0399h-64.68l-77.3 102.5399V5.36011h-53.24V305.06h53.24V201.17l87.95 103.89h64.28zm-795.07-94.64v94.64h-52.85v-22.7c-16.27 18.33-39.33 29.01-65.86 29.01-56.4 0-102.54-49.69-102.54-110.02S513.09 89.3501 577.38 89.3501c71.78 0 109.64 52.8399 109.64 121.0599m-53.24-9.86c0-35.1-24.45-62.31-57.58-62.31s-58.77 27.21-58.77 62.31 25.64 61.91 58.77 61.91 57.58-26.82 57.58-61.91m453.93 0c0 61.12-50.48 110.81-112.4 110.81s-112-49.69-112-110.81 50.87-111.1999 112-111.1999 112.4 50.0799 112.4 111.1999m-52.85 0c0-35.49-26.03-62.31-59.55-62.31s-59.15 27.21-59.15 62.31 25.63 61.91 59.15 61.91 59.55-27.21 59.55-61.91m-583.68-2.36c0 5.13-.4 13.8-1.18 22.87H285.4c7.99 25.74 31.55 41.8 64.83 41.8 25.24 0 49.3-9.07 69.8-26.42v54.81c-17.75 12.62-42.59 20.11-71.38 20.11-68.62 0-117.53-45.35-117.53-109.23s50.09-112.7799 112-112.7799S451.58 137.85 451.18 198.19M285.8 178.87h110.56c-6.82-24.48-26.88-41.01-53.63-41.01s-48.96 16.56-56.92 41.01z"/></g><defs><linearGradient id="b" x1="1575.74" x2="1575.74" y1="-.83" y2="400.19" gradientUnits="userSpaceOnUse"><stop stop-color="#ffdc23"/><stop offset=".16" stop-color="#ff8700"/><stop offset=".21" stop-color="#ff5401"/><stop offset=".37" stop-color="#d9005a"/><stop offset=".42" stop-color="#c814c8"/><stop offset=".58" stop-color="#8250ff"/><stop offset=".63" stop-color="#6e64ff"/><stop offset=".79" stop-color="#00c8ff"/><stop offset=".84" stop-color="#0c9"/><stop offset=".99" stop-color="#00a637"/></linearGradient><clipPath id="a"><path fill="#000" d="M0 0h1606.99v400H0z"/></clipPath></defs></svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
Reference in New Issue
Block a user