Show hover elements when keyboard focus is within an event tile (#31078)

* Show timestamps when keyboard focus is within an event tile

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Ensure toolbar navigation pattern works in MessageActionBar

This requires all buttons within to be roving by using the ref callback given by useRovingTabIndex

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Use PureComponent in EventTile to avoid mass re-rendering due to transitive onFocus/onBlur calls

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Remove unused timestamp event tile prop

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Use MessageTimestamp to generate the wrapping anchor so that focusing it brings up the tooltip

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Tweak MessageTimestamp

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Switch back to Component as we specify a shouldComponentUpdate already

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update jest tests

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update playwright timestamp masks

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Revert snapshot

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update snapshot

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Fix IRC layout

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Use PureComponent in EventTile to avoid mass re-rendering due to transitive onFocus/onBlur calls

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Remove unused timestamp event tile prop

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Use MessageTimestamp to generate the wrapping anchor so that focusing it brings up the tooltip

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Tweak MessageTimestamp

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Switch back to Component as we specify a shouldComponentUpdate already

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update jest tests

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update playwright timestamp masks

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Revert snapshot

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update snapshot

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Fix IRC layout

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Lint styles

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Fix layout picker

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update snapshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update screenshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Fix pcss comment

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate Playwright

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate Playwright

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski
2025-10-28 09:33:02 +00:00
committed by GitHub
parent 7e04998a58
commit f6731ec318
78 changed files with 280 additions and 124 deletions

View File

@@ -92,7 +92,7 @@ test.describe("Audio player", { tag: ["@no-firefox", "@no-webkit"] }, () => {
css: `
/* The timestamp is of inconsistent width depending on the time the test runs at */
.mx_MessageTimestamp {
display: none !important;
visibility: hidden;
}
/* The MAB showing up on hover is not needed for the test */
.mx_MessageActionBar {

View File

@@ -124,11 +124,12 @@ test.describe("HTML Export", () => {
const zip = await extractZipFileToPath(zipPath, dirPath);
await page.goto(`file://${dirPath}/${Object.keys(zip.files)[0]}/messages.html`);
await expect(page).toMatchScreenshot("html-export.png", {
mask: [
// We need to mask the whole thing because the width of the time part changes
page.locator(".mx_TimelineSeparator"),
page.locator(".mx_MessageTimestamp"),
],
mask: [page.locator(".mx_TimelineSeparator")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
});
},
);

View File

@@ -138,7 +138,11 @@ test.describe("Editing", () => {
// Take a snapshot of the dialog
await expect(dialog).toMatchScreenshot("message-edit-history-dialog.png", {
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
});
{

View File

@@ -59,9 +59,11 @@ async function editMessage(page: Page, message: Locator, newMsg: string): Promis
}
const screenshotOptions = (page?: Page) => ({
mask: page ? [page.locator(".mx_MessageTimestamp")] : undefined,
// Hide the jump to bottom button in the timeline to avoid flakiness
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
.mx_JumpToBottomButton {
display: none !important;
}

View File

@@ -11,10 +11,12 @@ import fs from "node:fs";
import { test, expect } from "../../element-web-test";
const screenshotOptions = (page: Page) => ({
mask: [page.locator(".mx_MessageTimestamp")],
// Hide the jump to bottom button in the timeline to avoid flakiness
// Exclude timestamp and read marker from snapshot
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
.mx_JumpToBottomButton {
display: none !important;
}

View File

@@ -93,10 +93,12 @@ test.describe("permalinks", () => {
getPill(timeline, danielleId);
await expect(timeline).toMatchScreenshot("permalink-rendering.png", {
mask: [
// Exclude timestamps from the snapshot, for consistency.
page.locator(".mx_MessageTimestamp"),
],
// Exclude timestamps from the snapshot, for consistency.
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
});
});
});

View File

@@ -121,7 +121,11 @@ test.describe("Polls", () => {
.filter({ hasText: pollParams.title })
.getAttribute("data-scroll-tokens");
await expect(getPollTile(page, pollId)).toMatchScreenshot("Polls_Timeline_tile_no_votes.png", {
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
});
// Bot votes 'Maybe' in the poll
@@ -293,7 +297,11 @@ test.describe("Polls", () => {
await expect(page.locator(".mx_ThreadView")).toMatchScreenshot(
"ThreadView_with_a_poll_on_bubble_layout.png",
{
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
},
);
@@ -303,7 +311,11 @@ test.describe("Polls", () => {
await expect(page.locator(".mx_ThreadView")).toMatchScreenshot(
"ThreadView_with_a_poll_on_group_layout.png",
{
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
},
);

View File

@@ -126,7 +126,12 @@ test.describe("FilePanel", () => {
// Take a snapshot of file tiles list on FilePanel
await expect(filePanelMessageList).toMatchScreenshot("file-tiles-list.png", {
// Exclude timestamps & flaky seek bar from snapshot
mask: [page.locator(".mx_MessageTimestamp"), page.getByTestId("audio-player-seek")],
mask: [page.getByTestId("audio-player-seek")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
});
});

View File

@@ -361,7 +361,9 @@ test.describe("Sliding Sync", () => {
await expect(page.locator(".mx_ReplyPreview")).toBeVisible();
// now click on the permalink for Permalink me
await page.locator(".mx_EventTile").filter({ hasText: "Permalink me" }).locator("a").dispatchEvent("click");
const tile = page.locator(".mx_EventTile").filter({ hasText: "Permalink me" });
await tile.hover();
await tile.locator("a").dispatchEvent("click");
// make sure it is now selected with the little green |
await expect(page.locator(".mx_EventTile_selected").filter({ hasText: "Permalink me" })).toBeVisible();

View File

@@ -39,7 +39,12 @@ test.describe("Threads", () => {
const ThreadViewGroupSpacingStart = "56px"; // --ThreadView_group_spacing-start
// Exclude timestamp and read marker from snapshots
const mask = [page.locator(".mx_MessageTimestamp"), page.locator(".mx_MessagePanel_myReadMarker")];
const mask = [page.locator(".mx_MessagePanel_myReadMarker")];
const css = `
.mx_MessageTimestamp {
visibility: hidden;
}
`;
const roomViewLocator = page.locator(".mx_RoomView_body");
// User sends message
@@ -74,13 +79,15 @@ test.describe("Threads", () => {
// Take snapshots in group layout and bubble layout (IRC layout is not available on ThreadView)
await expect(page.locator(".mx_ThreadView")).toMatchScreenshot("Initial_ThreadView_on_group_layout.png", {
mask: mask,
mask,
css,
});
await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Bubble);
await expect(page.locator(".mx_ThreadView .mx_EventTile[data-layout='bubble']")).toHaveCount(2);
await expect(page.locator(".mx_ThreadView")).toMatchScreenshot("Initial_ThreadView_on_bubble_layout.png", {
mask: mask,
mask,
css,
});
// Set the group layout
@@ -154,7 +161,8 @@ test.describe("Threads", () => {
await expect(page.locator(".mx_ThreadView")).toMatchScreenshot(
"ThreadView_with_reaction_and_a_hidden_event_on_group_layout.png",
{
mask: mask,
mask,
css,
},
);
@@ -178,7 +186,8 @@ test.describe("Threads", () => {
await expect(page.locator(".mx_ThreadView")).toMatchScreenshot(
"ThreadView_with_reaction_and_a_hidden_event_on_bubble_layout.png",
{
mask: mask,
mask,
css,
},
);
@@ -214,7 +223,8 @@ test.describe("Threads", () => {
await expect(page.locator(".mx_ThreadView")).toMatchScreenshot(
"ThreadView_with_redacted_messages_on_group_layout.png",
{
mask: mask,
mask,
css,
},
);
await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Bubble);
@@ -222,7 +232,8 @@ test.describe("Threads", () => {
await expect(page.locator(".mx_ThreadView")).toMatchScreenshot(
"ThreadView_with_redacted_messages_on_bubble_layout.png",
{
mask: mask,
mask,
css,
},
);

View File

@@ -181,8 +181,10 @@ test.describe("Timeline", () => {
await expect(gels.getByRole("button", { name: "Collapse" })).toBeVisible();
await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("expanded-gels-irc-layout.png", {
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
.mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker {
display: none !important;
}
@@ -215,8 +217,10 @@ test.describe("Timeline", () => {
await expect(gels.getByRole("button", { name: "Collapse" })).toBeVisible();
await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("expanded-gels-modern-layout.png", {
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
.mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker {
display: none !important;
}
@@ -255,7 +259,11 @@ test.describe("Timeline", () => {
// Save snapshot of expanded generic event list summary on bubble layout
await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("expanded-gels-bubble-layout.png", {
// Exclude timestamp from snapshot
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
});
// Click "collapse" link button on the first hovered info event line
@@ -271,7 +279,11 @@ test.describe("Timeline", () => {
// Save snapshot of collapsed generic event list summary on bubble layout
await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("collapsed-gels-bubble-layout.png", {
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
});
},
);
@@ -312,12 +324,14 @@ test.describe("Timeline", () => {
"event-line-inline-start-margin-irc-layout.png",
{
// Exclude timestamp and read marker from snapshot
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker {
display: none !important;
}
`,
.mx_MessageTimestamp {
visibility: hidden;
}
.mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker {
display: none !important;
}
`,
},
);
await expect(axe).toHaveNoViolations();
@@ -409,7 +423,11 @@ test.describe("Timeline", () => {
"collapsed-gels-and-messages-irc-layout.png",
{
// Exclude timestamp from snapshot of mx_MainSplit
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
},
);
@@ -428,7 +446,11 @@ test.describe("Timeline", () => {
"expanded-gels-and-messages-irc-layout.png",
{
// Exclude timestamp from snapshot of mx_MainSplit
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
},
);
@@ -453,7 +475,11 @@ test.describe("Timeline", () => {
"expanded-gels-redaction-placeholder.png",
{
// Exclude timestamp from snapshot of mx_MainSplit
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
},
);
@@ -481,7 +507,11 @@ test.describe("Timeline", () => {
// Record alignment of expanded GELS, placeholder of deleted message, and emote
await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("expanded-gels-emote-irc-layout.png", {
// Exclude timestamp from snapshot of mx_MainSplit
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
});
},
);
@@ -492,12 +522,14 @@ test.describe("Timeline", () => {
async ({ page, app, room }) => {
const screenshotOptions = {
// Hide because flaky - See https://github.com/vector-im/element-web/issues/24957
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker {
display: none !important;
}
`,
.mx_MessageTimestamp {
visibility: hidden;
}
.mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker {
display: none !important;
}
`,
};
await sendEvent(app.client, room.roomId);
@@ -605,12 +637,10 @@ test.describe("Timeline", () => {
await messageEdit(page);
// Click timestamp to highlight hidden event line
const timestamp = page.locator(".mx_RoomView_body .mx_EventTile_info a", {
has: page.locator(".mx_MessageTimestamp"),
});
const timestamp = page.locator(".mx_RoomView_body .mx_EventTile_info a.mx_MessageTimestamp");
// wait for the remote echo otherwise we get an error modal due to a 404 on the /event/ API
await expect(timestamp).not.toHaveAttribute("href", /~!/);
await timestamp.locator(".mx_MessageTimestamp").click();
await timestamp.click();
// should not add inline start padding to a hidden event line on IRC layout
await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC);
@@ -620,12 +650,14 @@ test.describe("Timeline", () => {
// Exclude timestamp and read marker from snapshot
const screenshotOptions = {
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker {
display: none !important;
}
`,
.mx_MessageTimestamp {
visibility: hidden;
}
.mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker {
display: none !important;
}
`,
};
await expect(page.locator(".mx_MainSplit")).toMatchScreenshot(
@@ -654,7 +686,11 @@ test.describe("Timeline", () => {
// Exclude timestamp from snapshot
const screenshotOptions = {
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
};
await sendEvent(app.client, room.roomId);
@@ -795,8 +831,10 @@ test.describe("Timeline", () => {
await app.timeline.scrollToBottom();
await expect(page.locator(".mx_EventTile_last")).toMatchScreenshot("url-preview.png", {
// Exclude timestamp and read marker from snapshot
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
.mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker {
display: none !important;
}
@@ -892,7 +930,13 @@ test.describe("Timeline", () => {
const tile = page.locator(".mx_EventTile");
await expect(tile).toBeVisible();
await expect(tile).toMatchScreenshot("code-block.png", { mask: [page.locator(".mx_MessageTimestamp")] });
await expect(tile).toMatchScreenshot("code-block.png", {
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
});
// Edit a code block and assert the edited code block has been correctly rendered
await tile.hover();
@@ -904,7 +948,11 @@ test.describe("Timeline", () => {
const newTile = page.locator(".mx_EventTile");
await expect(newTile).toMatchScreenshot("edited-code-block.png", {
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
});
});
@@ -1107,8 +1155,10 @@ test.describe("Timeline", () => {
// Exclude timestamp and read marker from snapshot
const screenshotOptions = {
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
.mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker {
display: none !important;
}
@@ -1233,12 +1283,14 @@ test.describe("Timeline", () => {
// Exclude timestamp and read marker from snapshot
const screenshotOptions = {
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker {
display: none !important;
}
`,
.mx_MessageTimestamp {
visibility: hidden;
}
.mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker {
display: none !important;
}
`,
};
// Make sure the strings do not overflow on IRC layout
@@ -1297,8 +1349,10 @@ test.describe("Timeline", () => {
// Exclude timestamp and read marker from snapshot
const screenshotOptions = {
mask: [page.locator(".mx_MessageTimestamp")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
.mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker {
display: none !important;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB