Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚧 Initial Discord message components v2 implementation #1294

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

Log1x
Copy link
Collaborator

@Log1x Log1x commented Feb 21, 2025

🚧 Work in progress.

Completely blind & untested. Should be able to try it later today.

Edit: everything appears to be functional.

Screenshot

@Lulalaby
Copy link

P neat implementation ❤️ Good job!

@valzargaming
Copy link
Member

The v2 contract was an excellent idea, and something I'd like to see in other parts of the library. It would certainly cut down on a lost of instances of checking against hardcoded types like this.

Comment on lines +644 to +648
* @return int
*/
public function getFlags(): int
{
return $this->flags;
Copy link
Member

@SQKo SQKo Feb 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the property might be not set yet

Suggested change
* @return int
*/
public function getFlags(): int
{
return $this->flags;
* @return ?int
*/
public function getFlags(): ?int
{
return $this->flags;

@@ -181,6 +181,7 @@ class Message extends Part
public const FLAG_LOADING = (1 << 7);
public const FLAG_FAILED_TO_MENTION_SOME_ROLES_IN_THREAD = (1 << 8);
public const FLAG_SUPPRESS_NOTIFICATIONS = (1 << 12);
public const FLAG_V2_COMPONENTS = (1 << 15);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The official name is IS_COMPONENTS_V2

Suggested change
public const FLAG_V2_COMPONENTS = (1 << 15);
public const FLAG_IS_V2_COMPONENTS = (1 << 15);

please also adjust the referencing code

if (isset($this->components) && count($this->components) >= 10) {
throw new \OverflowException('You can only add 10 components to a v2 message');
}
} elseif (! ($component instanceof Components\ActionRow || $component instanceof Components\SelectMenu)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please import directly, so it is easy to update/refactor in future (or alias as seen in functions.php)

use Discord\Builders\Components\ActionRow;

use Discord\Builders\Components\SelectMenu;
Suggested change
} elseif (! ($component instanceof Components\ActionRow || $component instanceof Components\SelectMenu)) {
} elseif (! ($component instanceof ActionRow || $component instanceof SelectMenu)) {

Copy link
Member

@SQKo SQKo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also adjust the class implements Components\xx to have the namespace imported per my previous suggestion

'width' => $this->width ?? null,
'height' => $this->height ?? null,
'content_type' => $this->content_type ?? null,
'loading_state' => $this->loading_state ?? null,
Copy link
Member

@SQKo SQKo Feb 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'loading_state' => $this->loading_state ?? null,
'loading_state' => $this->loading_state,

loading_state will be always set since isResolved() returns true

public function setUrl(string $url): self
{
$this->url = $url;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implement validation of $url like in Embed::ensureValidUrl()

Comment on lines +62 to +68
* @param string $url URL of the media item.
*
* @return $this
*/
public function setMedia(string $url): self
{
$this->media = ['url' => $url];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec actually expects the media to contain UnfurledMediaItem, even though only the url for now that will be taken, that is what you can deal with inside jsonSerialize()

Needs to change on the getter too

For example

Suggested change
* @param string $url URL of the media item.
*
* @return $this
*/
public function setMedia(string $url): self
{
$this->media = ['url' => $url];
* @param UnfurledMediaItem|string $url URL of the media item.
*
* @return $this
*/
public function setMedia(UnfurledMediaItem|string $url): self
{
if (is_string($url)) {
$url = UnfurledMediaItem::new($url);
}
$this->media = $url;

with this we can anticipate more changes in future

Comment on lines +88 to +106
/**
* Set the spacing size to small.
*
* @return $this
*/
public function setSpacingSmall(): self
{
return $this->setSpacing(self::SPACING_SMALL);
}

/**
* Set the spacing size to large.
*
* @return $this
*/
public function setSpacingLarge(): self
{
return $this->setSpacing(self::SPACING_LARGE);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/**
* Set the spacing size to small.
*
* @return $this
*/
public function setSpacingSmall(): self
{
return $this->setSpacing(self::SPACING_SMALL);
}
/**
* Set the spacing size to large.
*
* @return $this
*/
public function setSpacingLarge(): self
{
return $this->setSpacing(self::SPACING_LARGE);
}

Don't think this is necessary when there is a setSpacing() already, we don't want the code to get huge when there is another type of spacing in future

public function addComponent(Component $component): self
{
if (! ($component instanceof TextDisplay)) {
throw new \InvalidArgumentException('Section can only contain TextDisplay components. Use setAccessory() for Thumbnail or Button.');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new \InvalidArgumentException('Section can only contain TextDisplay components. Use setAccessory() for Thumbnail or Button.');
throw new \InvalidArgumentException('Section can only contain TextDisplay components.');

You are not checking wether the $component is a Thumbnail or Button here so it's better not to explicitly say that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a second though, the spec is telling us to not hardcode this, so we should not validate this yet

Suggested change
throw new \InvalidArgumentException('Section can only contain TextDisplay components. Use setAccessory() for Thumbnail or Button.');
trigger_error('Section may only contain TextDisplay components.', E_USER_NOTICE);

Comment on lines +83 to +85
public function setAccessory(Thumbnail|Button $component): self
{
$this->accessory = $component;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec is telling us to not hard code the supported components yet (anyway leave the phpdoc as is)

Suggested change
public function setAccessory(Thumbnail|Button $component): self
{
$this->accessory = $component;
public function setAccessory(Component $component): self
{
if (! ($component instanceof Thumbnail || $component instanceof Button)) {
trigger_error('Accessory may only contain Thumbnail or Button component.', E_USER_NOTICE);
}
$this->accessory = $component;

*/
public function setDescription(?string $description): self
{
if ($description !== null && strlen($description) > 1024) {
Copy link
Member

@SQKo SQKo Feb 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if ($description !== null && strlen($description) > 1024) {
if ($description !== null && poly_strlen($description) > 1024) {

multibyte

if (count($this->components) >= 10) {
throw new \OverflowException('You can only have 10 components per container.');
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might want to validate the component type that can be added here or perhaps strict type them

@SQKo
Copy link
Member

SQKo commented Feb 23, 2025

According to the spec, using the components v2 may disable content and embeds, it would be good to warn the users in the MessageBuilder to avoid confusion

Also seems this PR has not supported webhooks yet

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants