[Store] Various internal improvements (React authors, lazy load banners, avatars)

pull/50/head
Oj18 3 years ago
parent b6d5d159ea
commit 59209e5d70

@ -224,36 +224,34 @@ export default {
},
parseAuthors: async (a) => {
let authors = [];
if (typeof a === "string") {
authors = a.split(', ');
} else if (Array.isArray(a)) {
authors = a;
};
const authors = typeof a === 'string' ? a.split(', ') : a;
return (await Promise.all(authors.map(async (x, i) => {
return (await Promise.all(authors.map(async (x) => {
if (typeof x === 'object') { // User object
const pfp = `<img style="display: inline; border-radius: 50%; margin-right: 5px; vertical-align: bottom;" src="https://cdn.discordapp.com/avatars/${x.i}/${x.a}.png?size=32">`;
const name = `<span class="author" style="cursor: pointer; line-height: 32px;" onmouseover="this.style.color = '#ccc'" onmouseout="this.style.color = '#fff'" onclick="try { window.goosemod.webpackModules.findByProps('open', 'fetchMutualFriends').open('${x.i}') } catch (e) { }">${x.n}</span>`; //<span class="description-3_Ncsb">#${result.discriminator}</span></span>`;
return i > 1 ? pfp : pfp + name;
return {
name: x.n,
id: x.i,
avatar: x.a
};
}
if (x.match(/^[0-9]{17,18}$/)) { // "<id>"
const result = await IDCache.getDataForID(x);
const pfp = `<img style="display: inline; border-radius: 50%; margin-right: 5px; vertical-align: bottom;" src="https://cdn.discordapp.com/avatars/${result.id}/${result.avatar}.png?size=32">`;
const name = `<span class="author" style="cursor: pointer; line-height: 32px;" onmouseover="this.style.color = '#ccc'" onmouseout="this.style.color = '#fff'" onclick="try { window.goosemod.webpackModules.findByProps('open', 'fetchMutualFriends').open('${result.id}') } catch (e) { }">${result.username}</span>`; //<span class="description-3_Ncsb">#${result.discriminator}</span></span>`;
return i > 1 ? pfp : pfp + name;
return {
name: result.username,
id: result.id,
avatar: result.avatar
};
}
let idMatch = x.match(/(.*) \(([0-9]{17,18})\)/); // "<name> (<id>)"
if (idMatch === null) return `<span class="author">${x}</span>`; // "<name>"
const idMatch = x.match(/(.*) \(([0-9]{17,18})\)/); // "<name> (<id>)"
return `<span class="author" style="cursor: pointer;" onmouseover="this.style.color = '#ccc'" onmouseout="this.style.color = '#fff'" onclick="try { window.goosemod.webpackModules.findByProps('open', 'fetchMutualFriends').open('${idMatch[2]}') } catch (e) { }">${idMatch[1]}</span>`; // todo
}))).join('<span class="description-3_Ncsb">,</span> ');
return {
name: idMatch?.[1] || x,
id: idMatch?.[2]
};
})));
},
updateStoreSetting: async () => {

@ -449,7 +449,7 @@ Modules: ${Object.keys(goosemodScope.modules).join(', ')}
const title = titles[1];
const authors = [...titles[0].getElementsByClassName('author')].map((x) => x.textContent.split('#')[0]);
const authors = [...titles[0].getElementsByClassName('gm-store-author-name')].map((x) => x.textContent.split('#')[0]);
const name = title.childNodes[0].wholeText;
const description = c.getElementsByClassName('description-3_Ncsb')[0].innerText;

@ -94,7 +94,7 @@ export default () => {
}
.gm-store-card > :nth-child(2).no-pfp {
padding: 4px 8px;
padding: 0px 8px;
}
.gm-store-card > :nth-child(3) {
@ -251,6 +251,18 @@ export default () => {
}
.gm-store-author-pfp {
display: inline;
border-radius: 50%;
margin-right: 5px;
vertical-align: bottom;
}
.gm-store-author-name {
line-height: 32px;
}
.gm-settings-note-markdown {
font-size: inherit;
color: inherit !important;

@ -321,7 +321,13 @@ export default async (goosemodScope) => {
images: x.attachments[0] ? [ x.attachments[0].proxy_url ] : (x.embeds[0] ? [ x.embeds[0].thumbnail.proxy_url ] : []),
name: '', // No name makes subtext main content (not gray)
author: `<img style="display: inline; border-radius: 50%; margin-right: 5px; vertical-align: bottom;" src="https://cdn.discordapp.com/avatars/${x.author.id}/${x.author.avatar}.png?size=32"><span class="author" style="line-height: 32px;">${x.author.username}</span>`, // Based off Store author generation
author: [
{
name: x.author.username,
id: x.author.id,
avatar: x.author.avatar
}
],
subtext: x.content.replace(/```css(.*)```/gs, ''), // Only context / text without code

@ -1,6 +1,9 @@
import _LazyBanner from './sub/lazyBanner';
export default () => {
const { React } = goosemod.webpackModules.common;
const LazyBanner = _LazyBanner();
const Button = goosemod.webpackModules.findByProps('Sizes', 'Colors', 'Looks', 'DropdownSizes');
const Switch = goosemod.webpackModules.findByDisplayName('Switch');
@ -26,8 +29,7 @@ return class Card extends React.PureComponent {
className: ['gm-store-card', this.props.mini ? 'gm-store-card-mini' : '', ...this.props.tags.map((x) => x.replace(/ /g, '|'))].join(' '),
onClick: this.props.onClick
},
React.createElement('div', {
/* React.createElement('div', {
style: {
backgroundImage: this.props.images?.length ? `url("${this.props.images[0]}")` : ''
},
@ -44,17 +46,43 @@ return class Card extends React.PureComponent {
})
));
}
}, this.props.images?.length ? '' : 'No Preview'),
}), */
React.createElement('div', {
className: [FormClasses.title, !this.props.author.includes('avatar') ? 'no-pfp' : ''].join(' '),
React.createElement(LazyBanner, {
src: this.props.images?.[0],
onClick: () => {
if (!this.props.images?.length) return; // Ignore if no images
ref: (ref) => {
if (!ref) return;
ref.innerHTML = this.props.author;
ModalHandler.openModal(() => React.createElement('div', {
className: 'gm-carousel-modal'
},
React.createElement(SmallMediaCarousel, {
items: this.props.images.map((x) => ({ type: 1, src: x })),
autoplayInterval: 5000 // Time between automatically cycling to next image
})
));
}
}),
React.createElement('div', {
className: [FormClasses.title, this.props.author.every((x) => !x.avatar) ? 'no-pfp' : ''].join(' '),
},
...this.props.author.map((x, i) => [
x.avatar ? React.createElement('img', {
loading: 'lazy',
src: `https://cdn.discordapp.com/avatars/${x.id}/${x.avatar}.png?size=32`,
className: 'gm-store-author-pfp'
}) : null,
React.createElement('span', {
className: 'gm-store-author-name'
}, x.name),
i !== this.props.author.length - 1 ? React.createElement('span', {
className: FormTextClasses.description
}, ',') : null
])
),
React.createElement('div', {
className: FormClasses.title,
}, this.props.name),

@ -0,0 +1,48 @@
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
const image = entry.target;
image._lazyLoad();
observer.unobserve(image);
}
}
});
export default () => {
const { React, ReactDOM } = goosemod.webpackModules.common;
return class LazyBanner extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
loaded: false
};
}
componentDidMount() {
const node = ReactDOM.findDOMNode(this);
node._lazyLoad = () => {
this.setState({
loaded: true
});
};
observer.observe(node);
}
render() {
return React.createElement('div', {
style: {
backgroundImage: this.state.loaded ? `url("${this.props.src}")` : ''
},
onClick: this.props.onclick
});
}
};
};

@ -3,7 +3,7 @@ import _Divider from './divider';
export default () => {
const { React } = goosemod.webpackModules.common;
const Divider = _Divider;
const Divider = _Divider();
const FormItem = goosemod.webpackModules.findByDisplayName('FormItem');
const FormText = goosemod.webpackModules.findByDisplayName('FormText');

Loading…
Cancel
Save