Refresh the sticker pack manager
This commit is contained in:
parent
fdfc0539a3
commit
94875efaf6
10 changed files with 550 additions and 627 deletions
|
@ -2352,8 +2352,16 @@
|
||||||
"message": "Sticker pack could not be installed",
|
"message": "Sticker pack could not be installed",
|
||||||
"description": "Shown in a toast if the user attempts to install a sticker pack and it fails"
|
"description": "Shown in a toast if the user attempts to install a sticker pack and it fails"
|
||||||
},
|
},
|
||||||
|
"stickers--StickerManager--title": {
|
||||||
|
"message": "Stickers",
|
||||||
|
"description": "Title for the sticker manager"
|
||||||
|
},
|
||||||
|
"stickers--StickerManager--Available": {
|
||||||
|
"message": "Available",
|
||||||
|
"description": "Shown in the sticker pack manager as a tab for available stickers"
|
||||||
|
},
|
||||||
"stickers--StickerManager--InstalledPacks": {
|
"stickers--StickerManager--InstalledPacks": {
|
||||||
"message": "Installed Stickers",
|
"message": "Installed",
|
||||||
"description": "Shown in the sticker pack manager above your installed sticker packs."
|
"description": "Shown in the sticker pack manager above your installed sticker packs."
|
||||||
},
|
},
|
||||||
"stickers--StickerManager--InstalledPacks--Empty": {
|
"stickers--StickerManager--InstalledPacks--Empty": {
|
||||||
|
|
|
@ -2713,6 +2713,10 @@ button.ConversationDetails__action-button {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.module-image--hidden {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.module-image--tap-to-play,
|
.module-image--tap-to-play,
|
||||||
.module-image--not-downloaded {
|
.module-image--not-downloaded {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -5741,421 +5745,6 @@ button.module-image__border-overlay:focus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Module: StickerManager
|
|
||||||
|
|
||||||
.module-sticker-manager {
|
|
||||||
padding: 0 16px;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-sticker-manager__text {
|
|
||||||
height: 18px;
|
|
||||||
|
|
||||||
letter-spacing: 0px;
|
|
||||||
line-height: 18px;
|
|
||||||
|
|
||||||
@include light-theme() {
|
|
||||||
color: $color-gray-60;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include dark-theme() {
|
|
||||||
color: $color-gray-25;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--heading {
|
|
||||||
@include font-body-1-bold;
|
|
||||||
|
|
||||||
@include light-theme() {
|
|
||||||
color: $color-gray-90;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include dark-theme() {
|
|
||||||
color: $color-gray-05;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-sticker-manager__empty {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 64px;
|
|
||||||
border-radius: 8px;
|
|
||||||
|
|
||||||
@include light-theme {
|
|
||||||
background: $color-gray-02;
|
|
||||||
color: $color-gray-60;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include dark-theme {
|
|
||||||
background: $color-gray-90;
|
|
||||||
color: $color-gray-25;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
%blessed-sticker-pack-icon {
|
|
||||||
height: 14px;
|
|
||||||
width: 14px;
|
|
||||||
border-radius: 8px;
|
|
||||||
background-color: $color-white;
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
margin: {
|
|
||||||
left: 5px;
|
|
||||||
bottom: 2px;
|
|
||||||
}
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
position: absolute;
|
|
||||||
top: -1px;
|
|
||||||
left: -1px;
|
|
||||||
|
|
||||||
@include light-theme {
|
|
||||||
@include color-svg(
|
|
||||||
'../images/icons/v2/check-circle-solid-24.svg',
|
|
||||||
$color-accent-blue
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@include dark-theme {
|
|
||||||
@include color-svg(
|
|
||||||
'../images/icons/v2/check-circle-solid-24.svg',
|
|
||||||
$color-accent-blue
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-sticker-manager__pack-row {
|
|
||||||
@include button-reset;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
padding: 16px;
|
|
||||||
|
|
||||||
@include light-theme {
|
|
||||||
& + & {
|
|
||||||
border-top: 1px solid $color-gray-15;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include dark-theme {
|
|
||||||
& + & {
|
|
||||||
border-top: 1px solid $color-gray-75;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include keyboard-mode {
|
|
||||||
&:focus {
|
|
||||||
box-shadow: 0px 0px 0px 2px $color-ultramarine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__cover {
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
&__cover-placeholder {
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
background: $color-gray-05;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__meta {
|
|
||||||
flex-grow: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
&:not(:first-child) {
|
|
||||||
padding: 0 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__title {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__author {
|
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
@include light-theme() {
|
|
||||||
color: $color-gray-45;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include dark-theme() {
|
|
||||||
color: $color-gray-25;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__blessed-icon {
|
|
||||||
@extend %blessed-sticker-pack-icon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__controls {
|
|
||||||
flex-shrink: 1;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
&__button {
|
|
||||||
background: none;
|
|
||||||
border: 0;
|
|
||||||
&--menu {
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
min-width: 24px;
|
|
||||||
min-height: 24px;
|
|
||||||
@include light-theme {
|
|
||||||
@include color-svg(
|
|
||||||
'../images/icons/v2/more-horiz-24.svg',
|
|
||||||
$color-gray-60
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@include dark-theme {
|
|
||||||
@include color-svg(
|
|
||||||
'../images/icons/v2/more-horiz-24.svg',
|
|
||||||
$color-gray-25
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-sticker-manager__install-button {
|
|
||||||
background: none;
|
|
||||||
border: 0;
|
|
||||||
color: $color-gray-90;
|
|
||||||
|
|
||||||
@include font-body-1-bold;
|
|
||||||
|
|
||||||
height: 24px;
|
|
||||||
background: $color-gray-05;
|
|
||||||
border-radius: 12px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 12px;
|
|
||||||
|
|
||||||
@include dark-theme {
|
|
||||||
color: $color-gray-05;
|
|
||||||
background: $color-gray-75;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include mouse-mode {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--blue {
|
|
||||||
@include light-theme {
|
|
||||||
background: $color-ultramarine;
|
|
||||||
color: $color-white;
|
|
||||||
}
|
|
||||||
@include dark-theme {
|
|
||||||
background: $color-ultramarine-light;
|
|
||||||
color: $color-white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-sticker-manager__preview-modal {
|
|
||||||
&__overlay {
|
|
||||||
background: $color-black-alpha-40;
|
|
||||||
position: fixed;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: var(--window-width);
|
|
||||||
height: var(--window-height);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
z-index: $z-index-popup-overlay;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__container {
|
|
||||||
position: relative;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 4px 12px 0 $color-black-alpha-20;
|
|
||||||
width: 440px;
|
|
||||||
height: 360px;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
@include light-theme {
|
|
||||||
background: $color-white;
|
|
||||||
}
|
|
||||||
@include dark-theme {
|
|
||||||
background: $color-gray-75;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__error {
|
|
||||||
color: $color-accent-red;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
text-align: center;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
padding: 0 80px 30px 80px;
|
|
||||||
|
|
||||||
@include font-body-1-bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__header {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-shrink: 0;
|
|
||||||
height: 36px;
|
|
||||||
padding: 0 8px 0 16px;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
&__text {
|
|
||||||
@include font-body-1-bold;
|
|
||||||
|
|
||||||
color: $color-gray-90;
|
|
||||||
@include dark-theme {
|
|
||||||
color: $color-gray-05;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__close-button {
|
|
||||||
border: none;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
@include light-theme {
|
|
||||||
@include color-svg('../images/icons/v2/x-24.svg', $color-gray-60);
|
|
||||||
}
|
|
||||||
@include dark-theme {
|
|
||||||
@include color-svg('../images/icons/v2/x-24.svg', $color-gray-05);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__sticker-grid {
|
|
||||||
width: 100%;
|
|
||||||
display: grid;
|
|
||||||
grid-gap: 8px;
|
|
||||||
grid-template-columns: repeat(4, 1fr);
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
padding: 0 16px;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
height: 80px;
|
|
||||||
grid-column: 1 / span 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__cell {
|
|
||||||
width: 96px;
|
|
||||||
height: 96px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
&__image {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--placeholder {
|
|
||||||
border-radius: 4px;
|
|
||||||
|
|
||||||
@include light-theme() {
|
|
||||||
background: $color-gray-05;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include dark-theme() {
|
|
||||||
background: $color-gray-60;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__meta-overlay {
|
|
||||||
border-radius: 4px;
|
|
||||||
width: 408px;
|
|
||||||
height: 52px;
|
|
||||||
position: absolute;
|
|
||||||
left: 16px;
|
|
||||||
bottom: 16px;
|
|
||||||
padding: 0 12px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
@include light-theme {
|
|
||||||
background: $color-gray-05;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include dark-theme {
|
|
||||||
background: $color-gray-60;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__info {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
&__title {
|
|
||||||
margin: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
@include font-body-1-bold;
|
|
||||||
|
|
||||||
@include light-theme {
|
|
||||||
color: $color-gray-90;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include dark-theme {
|
|
||||||
color: $color-gray-05;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__author {
|
|
||||||
margin: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
@include light-theme {
|
|
||||||
color: $color-gray-45;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include dark-theme {
|
|
||||||
color: $color-gray-25;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__blessed-icon {
|
|
||||||
@extend %blessed-sticker-pack-icon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__install {
|
|
||||||
flex-shrink: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Module: Sticker button (launches the sticker picker)
|
// Module: Sticker button (launches the sticker picker)
|
||||||
|
|
||||||
.sticker-button-wrapper {
|
.sticker-button-wrapper {
|
||||||
|
|
323
stylesheets/components/StickerManager.scss
Normal file
323
stylesheets/components/StickerManager.scss
Normal file
|
@ -0,0 +1,323 @@
|
||||||
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
.module-sticker-manager {
|
||||||
|
padding: 0 16px;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-sticker-manager__text {
|
||||||
|
height: 18px;
|
||||||
|
|
||||||
|
letter-spacing: 0px;
|
||||||
|
line-height: 18px;
|
||||||
|
padding-left: 8px;
|
||||||
|
|
||||||
|
@include light-theme() {
|
||||||
|
color: $color-gray-60;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include dark-theme() {
|
||||||
|
color: $color-gray-25;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--heading {
|
||||||
|
@include font-body-1-bold;
|
||||||
|
|
||||||
|
@include light-theme() {
|
||||||
|
color: $color-gray-90;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include dark-theme() {
|
||||||
|
color: $color-gray-05;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-sticker-manager__empty {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 64px;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
@include light-theme {
|
||||||
|
background: $color-gray-02;
|
||||||
|
color: $color-gray-60;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include dark-theme {
|
||||||
|
background: $color-gray-90;
|
||||||
|
color: $color-gray-25;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%blessed-sticker-pack-icon {
|
||||||
|
height: 14px;
|
||||||
|
width: 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: $color-white;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: {
|
||||||
|
left: 5px;
|
||||||
|
bottom: 2px;
|
||||||
|
}
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
position: absolute;
|
||||||
|
top: -1px;
|
||||||
|
left: -1px;
|
||||||
|
|
||||||
|
@include light-theme {
|
||||||
|
@include color-svg(
|
||||||
|
'../images/icons/v2/check-circle-solid-24.svg',
|
||||||
|
$color-accent-blue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@include dark-theme {
|
||||||
|
@include color-svg(
|
||||||
|
'../images/icons/v2/check-circle-solid-24.svg',
|
||||||
|
$color-accent-blue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-sticker-manager__pack-row {
|
||||||
|
@include button-reset;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 16px;
|
||||||
|
padding-left: 8px;
|
||||||
|
|
||||||
|
@include keyboard-mode {
|
||||||
|
&:focus {
|
||||||
|
box-shadow: 0px 0px 0px 2px $color-ultramarine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__cover {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
&__cover-placeholder {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
background: $color-gray-05;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__meta {
|
||||||
|
flex-grow: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
&:not(:first-child) {
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__author {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
@include light-theme() {
|
||||||
|
color: $color-gray-45;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include dark-theme() {
|
||||||
|
color: $color-gray-25;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__blessed-icon {
|
||||||
|
@extend %blessed-sticker-pack-icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__controls {
|
||||||
|
flex-shrink: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&__button {
|
||||||
|
background: none;
|
||||||
|
border: 0;
|
||||||
|
&--menu {
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
min-width: 24px;
|
||||||
|
min-height: 24px;
|
||||||
|
@include light-theme {
|
||||||
|
@include color-svg(
|
||||||
|
'../images/icons/v2/more-horiz-24.svg',
|
||||||
|
$color-gray-60
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@include dark-theme {
|
||||||
|
@include color-svg(
|
||||||
|
'../images/icons/v2/more-horiz-24.svg',
|
||||||
|
$color-gray-25
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-sticker-manager__install-button {
|
||||||
|
background: none;
|
||||||
|
border: 0;
|
||||||
|
color: $color-gray-90;
|
||||||
|
|
||||||
|
@include font-body-1-bold;
|
||||||
|
|
||||||
|
height: 24px;
|
||||||
|
background: $color-gray-05;
|
||||||
|
border-radius: 12px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 12px;
|
||||||
|
|
||||||
|
@include dark-theme {
|
||||||
|
color: $color-gray-05;
|
||||||
|
background: $color-gray-75;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include mouse-mode {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--blue {
|
||||||
|
@include light-theme {
|
||||||
|
background: $color-ultramarine;
|
||||||
|
color: $color-white;
|
||||||
|
}
|
||||||
|
@include dark-theme {
|
||||||
|
background: $color-ultramarine-light;
|
||||||
|
color: $color-white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-sticker-manager__preview-modal {
|
||||||
|
&__modal.module-Modal {
|
||||||
|
max-width: 440px;
|
||||||
|
width: 440px;
|
||||||
|
}
|
||||||
|
&__error {
|
||||||
|
color: $color-accent-red;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 80px 30px 80px;
|
||||||
|
|
||||||
|
@include font-body-1-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__sticker-grid {
|
||||||
|
width: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 8px;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
&__cell {
|
||||||
|
width: 96px;
|
||||||
|
height: 96px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&__image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--placeholder {
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
@include light-theme() {
|
||||||
|
background: $color-gray-05;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include dark-theme() {
|
||||||
|
background: $color-gray-60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&--info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--title {
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
@include font-body-1-bold;
|
||||||
|
|
||||||
|
@include light-theme {
|
||||||
|
color: $color-gray-90;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include dark-theme {
|
||||||
|
color: $color-gray-05;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--author {
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
@include light-theme {
|
||||||
|
color: $color-gray-45;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include dark-theme {
|
||||||
|
color: $color-gray-25;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--blessed-icon {
|
||||||
|
@extend %blessed-sticker-pack-icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--install {
|
||||||
|
flex-shrink: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -111,14 +111,15 @@
|
||||||
@import './components/SignalConnectionsModal.scss';
|
@import './components/SignalConnectionsModal.scss';
|
||||||
@import './components/Slider.scss';
|
@import './components/Slider.scss';
|
||||||
@import './components/StagedLinkPreview.scss';
|
@import './components/StagedLinkPreview.scss';
|
||||||
|
@import './components/StickerManager.scss';
|
||||||
@import './components/Stories.scss';
|
@import './components/Stories.scss';
|
||||||
|
@import './components/StoriesSettingsModal.scss';
|
||||||
@import './components/StoryCreator.scss';
|
@import './components/StoryCreator.scss';
|
||||||
@import './components/StoryDetailsModal.scss';
|
@import './components/StoryDetailsModal.scss';
|
||||||
@import './components/StoryImage.scss';
|
@import './components/StoryImage.scss';
|
||||||
@import './components/StoryLinkPreview.scss';
|
@import './components/StoryLinkPreview.scss';
|
||||||
@import './components/StoryListItem.scss';
|
@import './components/StoryListItem.scss';
|
||||||
@import './components/StoryReplyQuote.scss';
|
@import './components/StoryReplyQuote.scss';
|
||||||
@import './components/StoriesSettingsModal.scss';
|
|
||||||
@import './components/StoryViewer.scss';
|
@import './components/StoryViewer.scss';
|
||||||
@import './components/StoryViewsNRepliesModal.scss';
|
@import './components/StoryViewsNRepliesModal.scss';
|
||||||
@import './components/SystemMessage.scss';
|
@import './components/SystemMessage.scss';
|
||||||
|
|
|
@ -44,6 +44,7 @@ const knownPacks = [
|
||||||
|
|
||||||
const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||||
blessedPacks: overrideProps.blessedPacks || [],
|
blessedPacks: overrideProps.blessedPacks || [],
|
||||||
|
closeStickerPackPreview: action('closeStickerPackPreview'),
|
||||||
downloadStickerPack: action('downloadStickerPack'),
|
downloadStickerPack: action('downloadStickerPack'),
|
||||||
i18n,
|
i18n,
|
||||||
installStickerPack: action('installStickerPack'),
|
installStickerPack: action('installStickerPack'),
|
||||||
|
|
|
@ -1,35 +1,42 @@
|
||||||
// Copyright 2019-2020 Signal Messenger, LLC
|
// Copyright 2019-2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import classNames from 'classnames';
|
|
||||||
import { StickerManagerPackRow } from './StickerManagerPackRow';
|
import { StickerManagerPackRow } from './StickerManagerPackRow';
|
||||||
import { StickerPreviewModal } from './StickerPreviewModal';
|
import { StickerPreviewModal } from './StickerPreviewModal';
|
||||||
import type { LocalizerType } from '../../types/Util';
|
import type { LocalizerType } from '../../types/Util';
|
||||||
import type { StickerPackType } from '../../state/ducks/stickers';
|
import type { StickerPackType } from '../../state/ducks/stickers';
|
||||||
|
import { Tabs } from '../Tabs';
|
||||||
|
|
||||||
export type OwnProps = {
|
export type OwnProps = {
|
||||||
readonly installedPacks: ReadonlyArray<StickerPackType>;
|
|
||||||
readonly receivedPacks: ReadonlyArray<StickerPackType>;
|
|
||||||
readonly blessedPacks: ReadonlyArray<StickerPackType>;
|
readonly blessedPacks: ReadonlyArray<StickerPackType>;
|
||||||
readonly knownPacks?: ReadonlyArray<StickerPackType>;
|
readonly closeStickerPackPreview: (packId: string) => unknown;
|
||||||
readonly downloadStickerPack: (packId: string, packKey: string) => unknown;
|
readonly downloadStickerPack: (packId: string, packKey: string) => unknown;
|
||||||
readonly installStickerPack: (packId: string, packKey: string) => unknown;
|
|
||||||
readonly uninstallStickerPack: (packId: string, packKey: string) => unknown;
|
|
||||||
readonly i18n: LocalizerType;
|
readonly i18n: LocalizerType;
|
||||||
|
readonly installStickerPack: (packId: string, packKey: string) => unknown;
|
||||||
|
readonly installedPacks: ReadonlyArray<StickerPackType>;
|
||||||
|
readonly knownPacks?: ReadonlyArray<StickerPackType>;
|
||||||
|
readonly receivedPacks: ReadonlyArray<StickerPackType>;
|
||||||
|
readonly uninstallStickerPack: (packId: string, packKey: string) => unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Props = OwnProps;
|
export type Props = OwnProps;
|
||||||
|
|
||||||
|
enum TabViews {
|
||||||
|
Available = 'Available',
|
||||||
|
Installed = 'Installed',
|
||||||
|
}
|
||||||
|
|
||||||
export const StickerManager = React.memo(function StickerManagerInner({
|
export const StickerManager = React.memo(function StickerManagerInner({
|
||||||
installedPacks,
|
|
||||||
receivedPacks,
|
|
||||||
knownPacks,
|
|
||||||
blessedPacks,
|
blessedPacks,
|
||||||
|
closeStickerPackPreview,
|
||||||
downloadStickerPack,
|
downloadStickerPack,
|
||||||
installStickerPack,
|
|
||||||
uninstallStickerPack,
|
|
||||||
i18n,
|
i18n,
|
||||||
|
installStickerPack,
|
||||||
|
installedPacks,
|
||||||
|
knownPacks,
|
||||||
|
receivedPacks,
|
||||||
|
uninstallStickerPack,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const focusRef = React.createRef<HTMLDivElement>();
|
const focusRef = React.createRef<HTMLDivElement>();
|
||||||
const [packToPreview, setPackToPreview] =
|
const [packToPreview, setPackToPreview] =
|
||||||
|
@ -66,68 +73,94 @@ export const StickerManager = React.memo(function StickerManagerInner({
|
||||||
<>
|
<>
|
||||||
{packToPreview ? (
|
{packToPreview ? (
|
||||||
<StickerPreviewModal
|
<StickerPreviewModal
|
||||||
i18n={i18n}
|
closeStickerPackPreview={closeStickerPackPreview}
|
||||||
pack={packToPreview}
|
|
||||||
closeStickerPackPreview={clearPackToPreview}
|
|
||||||
downloadStickerPack={downloadStickerPack}
|
downloadStickerPack={downloadStickerPack}
|
||||||
|
i18n={i18n}
|
||||||
installStickerPack={installStickerPack}
|
installStickerPack={installStickerPack}
|
||||||
|
onClose={clearPackToPreview}
|
||||||
|
pack={packToPreview}
|
||||||
uninstallStickerPack={uninstallStickerPack}
|
uninstallStickerPack={uninstallStickerPack}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<div className="module-sticker-manager" tabIndex={-1} ref={focusRef}>
|
<div className="module-sticker-manager" tabIndex={-1} ref={focusRef}>
|
||||||
{[
|
<Tabs
|
||||||
{
|
initialSelectedTab={TabViews.Available}
|
||||||
i18nKey: 'stickers--StickerManager--InstalledPacks',
|
tabs={[
|
||||||
i18nEmptyKey: 'stickers--StickerManager--InstalledPacks--Empty',
|
{
|
||||||
packs: installedPacks,
|
id: TabViews.Available,
|
||||||
hideIfEmpty: false,
|
label: i18n('stickers--StickerManager--Available'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
i18nKey: 'stickers--StickerManager--BlessedPacks',
|
id: TabViews.Installed,
|
||||||
i18nEmptyKey: 'stickers--StickerManager--BlessedPacks--Empty',
|
label: i18n('stickers--StickerManager--InstalledPacks'),
|
||||||
packs: blessedPacks,
|
},
|
||||||
hideIfEmpty: true,
|
]}
|
||||||
},
|
>
|
||||||
{
|
{({ selectedTab }) => (
|
||||||
i18nKey: 'stickers--StickerManager--ReceivedPacks',
|
<>
|
||||||
i18nEmptyKey: 'stickers--StickerManager--ReceivedPacks--Empty',
|
{selectedTab === TabViews.Available && (
|
||||||
packs: receivedPacks,
|
<>
|
||||||
hideIfEmpty: false,
|
<h2 className="module-sticker-manager__text module-sticker-manager__text--heading">
|
||||||
},
|
{i18n('stickers--StickerManager--BlessedPacks')}
|
||||||
].map(section => {
|
</h2>
|
||||||
if (section.hideIfEmpty && section.packs.length === 0) {
|
{blessedPacks.length > 0 ? (
|
||||||
return null;
|
blessedPacks.map(pack => (
|
||||||
}
|
<StickerManagerPackRow
|
||||||
|
key={pack.id}
|
||||||
|
pack={pack}
|
||||||
|
i18n={i18n}
|
||||||
|
onClickPreview={previewPack}
|
||||||
|
installStickerPack={installStickerPack}
|
||||||
|
uninstallStickerPack={uninstallStickerPack}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<div className="module-sticker-manager__empty">
|
||||||
|
{i18n('stickers--StickerManager--BlessedPacks--Empty')}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
return (
|
<h2 className="module-sticker-manager__text module-sticker-manager__text--heading">
|
||||||
<React.Fragment key={section.i18nKey}>
|
{i18n('stickers--StickerManager--ReceivedPacks')}
|
||||||
<h2
|
</h2>
|
||||||
className={classNames(
|
{receivedPacks.length > 0 ? (
|
||||||
'module-sticker-manager__text',
|
receivedPacks.map(pack => (
|
||||||
'module-sticker-manager__text--heading'
|
<StickerManagerPackRow
|
||||||
)}
|
key={pack.id}
|
||||||
>
|
pack={pack}
|
||||||
{i18n(section.i18nKey)}
|
i18n={i18n}
|
||||||
</h2>
|
onClickPreview={previewPack}
|
||||||
{section.packs.length > 0 ? (
|
installStickerPack={installStickerPack}
|
||||||
section.packs.map(pack => (
|
uninstallStickerPack={uninstallStickerPack}
|
||||||
<StickerManagerPackRow
|
/>
|
||||||
key={pack.id}
|
))
|
||||||
pack={pack}
|
) : (
|
||||||
i18n={i18n}
|
<div className="module-sticker-manager__empty">
|
||||||
onClickPreview={previewPack}
|
{i18n('stickers--StickerManager--ReceivedPacks--Empty')}
|
||||||
installStickerPack={installStickerPack}
|
</div>
|
||||||
uninstallStickerPack={uninstallStickerPack}
|
)}
|
||||||
/>
|
</>
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<div className="module-sticker-manager__empty">
|
|
||||||
{i18n(section.i18nEmptyKey)}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
{selectedTab === TabViews.Installed &&
|
||||||
);
|
(installedPacks.length > 0 ? (
|
||||||
})}
|
installedPacks.map(pack => (
|
||||||
|
<StickerManagerPackRow
|
||||||
|
key={pack.id}
|
||||||
|
pack={pack}
|
||||||
|
i18n={i18n}
|
||||||
|
onClickPreview={previewPack}
|
||||||
|
installStickerPack={installStickerPack}
|
||||||
|
uninstallStickerPack={uninstallStickerPack}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<div className="module-sticker-manager__empty">
|
||||||
|
{i18n('stickers--StickerManager--InstalledPacks--Empty')}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
// Copyright 2019-2020 Signal Messenger, LLC
|
// Copyright 2019-2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { StickerPackInstallButton } from './StickerPackInstallButton';
|
|
||||||
import { ConfirmationDialog } from '../ConfirmationDialog';
|
import { ConfirmationDialog } from '../ConfirmationDialog';
|
||||||
import type { LocalizerType } from '../../types/Util';
|
import type { LocalizerType } from '../../types/Util';
|
||||||
import type { StickerPackType } from '../../state/ducks/stickers';
|
import type { StickerPackType } from '../../state/ducks/stickers';
|
||||||
|
import { Button, ButtonVariant } from '../Button';
|
||||||
|
|
||||||
export type OwnProps = {
|
export type OwnProps = {
|
||||||
readonly i18n: LocalizerType;
|
readonly i18n: LocalizerType;
|
||||||
|
@ -136,17 +136,21 @@ export const StickerManagerPackRow = React.memo(
|
||||||
</div>
|
</div>
|
||||||
<div className="module-sticker-manager__pack-row__controls">
|
<div className="module-sticker-manager__pack-row__controls">
|
||||||
{pack.status === 'installed' ? (
|
{pack.status === 'installed' ? (
|
||||||
<StickerPackInstallButton
|
<Button
|
||||||
installed
|
aria-label={i18n('stickers--StickerManager--Uninstall')}
|
||||||
i18n={i18n}
|
variant={ButtonVariant.Secondary}
|
||||||
onClick={handleUninstall}
|
onClick={handleUninstall}
|
||||||
/>
|
>
|
||||||
|
{i18n('stickers--StickerManager--Uninstall')}
|
||||||
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<StickerPackInstallButton
|
<Button
|
||||||
installed={false}
|
aria-label={i18n('stickers--StickerManager--Install')}
|
||||||
i18n={i18n}
|
variant={ButtonVariant.Secondary}
|
||||||
onClick={handleInstall}
|
onClick={handleInstall}
|
||||||
/>
|
>
|
||||||
|
{i18n('stickers--StickerManager--Install')}
|
||||||
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -65,6 +65,7 @@ export function Full(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<StickerPreviewModal
|
<StickerPreviewModal
|
||||||
closeStickerPackPreview={action('closeStickerPackPreview')}
|
closeStickerPackPreview={action('closeStickerPackPreview')}
|
||||||
|
onClose={action('onClose')}
|
||||||
installStickerPack={action('installStickerPack')}
|
installStickerPack={action('installStickerPack')}
|
||||||
uninstallStickerPack={action('uninstallStickerPack')}
|
uninstallStickerPack={action('uninstallStickerPack')}
|
||||||
downloadStickerPack={action('downloadStickerPack')}
|
downloadStickerPack={action('downloadStickerPack')}
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
// Copyright 2019-2020 Signal Messenger, LLC
|
// Copyright 2019-2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { createPortal } from 'react-dom';
|
|
||||||
import { isNumber, range } from 'lodash';
|
import { isNumber, range } from 'lodash';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { StickerPackInstallButton } from './StickerPackInstallButton';
|
|
||||||
import { ConfirmationDialog } from '../ConfirmationDialog';
|
import { ConfirmationDialog } from '../ConfirmationDialog';
|
||||||
import type { LocalizerType } from '../../types/Util';
|
import type { LocalizerType } from '../../types/Util';
|
||||||
import type { StickerPackType } from '../../state/ducks/stickers';
|
import type { StickerPackType } from '../../state/ducks/stickers';
|
||||||
import { Spinner } from '../Spinner';
|
import { Spinner } from '../Spinner';
|
||||||
import { useRestoreFocus } from '../../hooks/useRestoreFocus';
|
import { useRestoreFocus } from '../../hooks/useRestoreFocus';
|
||||||
|
import { Modal } from '../Modal';
|
||||||
|
import { Button, ButtonVariant } from '../Button';
|
||||||
|
|
||||||
export type OwnProps = {
|
export type OwnProps = {
|
||||||
readonly closeStickerPackPreview: () => unknown;
|
readonly onClose?: () => unknown;
|
||||||
|
readonly closeStickerPackPreview: (packId: string) => unknown;
|
||||||
readonly downloadStickerPack: (
|
readonly downloadStickerPack: (
|
||||||
packId: string,
|
packId: string,
|
||||||
packKey: string,
|
packKey: string,
|
||||||
|
@ -34,7 +35,7 @@ function renderBody({ pack, i18n }: Props) {
|
||||||
|
|
||||||
if (pack && pack.status === 'error') {
|
if (pack && pack.status === 'error') {
|
||||||
return (
|
return (
|
||||||
<div className="module-sticker-manager__preview-modal__container__error">
|
<div className="module-sticker-manager__preview-modal__error">
|
||||||
{i18n('stickers--StickerPreview--Error')}
|
{i18n('stickers--StickerPreview--Error')}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -45,29 +46,28 @@ function renderBody({ pack, i18n }: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="module-sticker-manager__preview-modal__container__sticker-grid">
|
<div className="module-sticker-manager__preview-modal__sticker-grid">
|
||||||
{pack.stickers.map(({ id, url }) => (
|
{pack.stickers.map(({ id, url }) => (
|
||||||
<div
|
<div
|
||||||
key={id}
|
key={id}
|
||||||
className="module-sticker-manager__preview-modal__container__sticker-grid__cell"
|
className="module-sticker-manager__preview-modal__sticker-grid__cell"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
className="module-sticker-manager__preview-modal__container__sticker-grid__cell__image"
|
className="module-sticker-manager__preview-modal__sticker-grid__cell__image"
|
||||||
src={url}
|
src={url}
|
||||||
alt={pack.title}
|
alt={pack.title}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{pack.status === 'pending' &&
|
{range(pack.stickerCount - pack.stickers.length).map(i => (
|
||||||
range(pack.stickerCount - pack.stickers.length).map(i => (
|
<div
|
||||||
<div
|
key={`placeholder-${i}`}
|
||||||
key={`placeholder-${i}`}
|
className={classNames(
|
||||||
className={classNames(
|
'module-sticker-manager__preview-modal__sticker-grid__cell',
|
||||||
'module-sticker-manager__preview-modal__container__sticker-grid__cell',
|
'module-sticker-manager__preview-modal__sticker-grid__cell--placeholder'
|
||||||
'module-sticker-manager__preview-modal__container__sticker-grid__cell--placeholder'
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
))}
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -77,28 +77,18 @@ export const StickerPreviewModal = React.memo(function StickerPreviewModalInner(
|
||||||
) {
|
) {
|
||||||
const {
|
const {
|
||||||
closeStickerPackPreview,
|
closeStickerPackPreview,
|
||||||
pack,
|
|
||||||
i18n,
|
|
||||||
downloadStickerPack,
|
downloadStickerPack,
|
||||||
|
i18n,
|
||||||
installStickerPack,
|
installStickerPack,
|
||||||
|
onClose,
|
||||||
|
pack,
|
||||||
uninstallStickerPack,
|
uninstallStickerPack,
|
||||||
} = props;
|
} = props;
|
||||||
const [root, setRoot] = React.useState<HTMLElement | null>(null);
|
|
||||||
const [confirmingUninstall, setConfirmingUninstall] = React.useState(false);
|
const [confirmingUninstall, setConfirmingUninstall] = React.useState(false);
|
||||||
|
|
||||||
// Restore focus on teardown
|
// Restore focus on teardown
|
||||||
const [focusRef] = useRestoreFocus();
|
const [focusRef] = useRestoreFocus();
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
const div = document.createElement('div');
|
|
||||||
document.body.appendChild(div);
|
|
||||||
setRoot(div);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.body.removeChild(div);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (pack && pack.status === 'known') {
|
if (pack && pack.status === 'known') {
|
||||||
downloadStickerPack(pack.id, pack.key);
|
downloadStickerPack(pack.id, pack.key);
|
||||||
|
@ -117,11 +107,12 @@ export const StickerPreviewModal = React.memo(function StickerPreviewModalInner(
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
React.useEffect(() => {
|
const handleClose = React.useCallback(() => {
|
||||||
if (!pack) {
|
if (pack?.id) {
|
||||||
closeStickerPackPreview();
|
closeStickerPackPreview(pack.id);
|
||||||
}
|
}
|
||||||
}, [pack, closeStickerPackPreview]);
|
onClose?.();
|
||||||
|
}, [closeStickerPackPreview, onClose, pack]);
|
||||||
|
|
||||||
const isInstalled = Boolean(pack && pack.status === 'installed');
|
const isInstalled = Boolean(pack && pack.status === 'installed');
|
||||||
const handleToggleInstall = React.useCallback(() => {
|
const handleToggleInstall = React.useCallback(() => {
|
||||||
|
@ -132,16 +123,16 @@ export const StickerPreviewModal = React.memo(function StickerPreviewModalInner(
|
||||||
setConfirmingUninstall(true);
|
setConfirmingUninstall(true);
|
||||||
} else if (pack.status === 'ephemeral') {
|
} else if (pack.status === 'ephemeral') {
|
||||||
downloadStickerPack(pack.id, pack.key, { finalStatus: 'installed' });
|
downloadStickerPack(pack.id, pack.key, { finalStatus: 'installed' });
|
||||||
closeStickerPackPreview();
|
handleClose();
|
||||||
} else {
|
} else {
|
||||||
installStickerPack(pack.id, pack.key);
|
installStickerPack(pack.id, pack.key);
|
||||||
closeStickerPackPreview();
|
handleClose();
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
downloadStickerPack,
|
downloadStickerPack,
|
||||||
installStickerPack,
|
installStickerPack,
|
||||||
isInstalled,
|
isInstalled,
|
||||||
closeStickerPackPreview,
|
handleClose,
|
||||||
pack,
|
pack,
|
||||||
setConfirmingUninstall,
|
setConfirmingUninstall,
|
||||||
]);
|
]);
|
||||||
|
@ -155,100 +146,70 @@ export const StickerPreviewModal = React.memo(function StickerPreviewModalInner(
|
||||||
// closeStickerPackPreview is called by <ConfirmationDialog />'s onClose
|
// closeStickerPackPreview is called by <ConfirmationDialog />'s onClose
|
||||||
}, [uninstallStickerPack, setConfirmingUninstall, pack]);
|
}, [uninstallStickerPack, setConfirmingUninstall, pack]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
const buttonLabel = isInstalled
|
||||||
const handler = ({ key }: KeyboardEvent) => {
|
? i18n('stickers--StickerManager--Uninstall')
|
||||||
if (key === 'Escape') {
|
: i18n('stickers--StickerManager--Install');
|
||||||
closeStickerPackPreview();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener('keydown', handler);
|
const modalFooter =
|
||||||
|
pack && pack.status !== 'error' ? (
|
||||||
return () => {
|
<div className="module-sticker-manager__preview-modal__footer">
|
||||||
document.removeEventListener('keydown', handler);
|
<div className="module-sticker-manager__preview-modal__footer--info">
|
||||||
};
|
<h3 className="module-sticker-manager__preview-modal__footer--title">
|
||||||
}, [closeStickerPackPreview]);
|
{pack.title}
|
||||||
|
{pack.isBlessed ? (
|
||||||
const handleClickToClose = React.useCallback(
|
<span className="module-sticker-manager__preview-modal__footer--blessed-icon" />
|
||||||
(e: React.MouseEvent) => {
|
) : null}
|
||||||
if (e.target === e.currentTarget) {
|
</h3>
|
||||||
closeStickerPackPreview();
|
<h4 className="module-sticker-manager__preview-modal__footer--author">
|
||||||
}
|
{pack.author}
|
||||||
},
|
</h4>
|
||||||
[closeStickerPackPreview]
|
</div>
|
||||||
);
|
<div className="module-sticker-manager__preview-modal__footer--install">
|
||||||
|
{pack.status === 'pending' ? (
|
||||||
return root
|
<Spinner svgSize="small" size="14px" />
|
||||||
? createPortal(
|
|
||||||
// Not really a button. Just a background which can be clicked to close modal
|
|
||||||
// eslint-disable-next-line max-len
|
|
||||||
// eslint-disable-next-line jsx-a11y/interactive-supports-focus, jsx-a11y/click-events-have-key-events
|
|
||||||
<div
|
|
||||||
role="button"
|
|
||||||
className="module-sticker-manager__preview-modal__overlay"
|
|
||||||
onClick={handleClickToClose}
|
|
||||||
>
|
|
||||||
{confirmingUninstall ? (
|
|
||||||
<ConfirmationDialog
|
|
||||||
dialogName="StickerPreviewModal.confirmUninstall"
|
|
||||||
i18n={i18n}
|
|
||||||
onClose={closeStickerPackPreview}
|
|
||||||
actions={[
|
|
||||||
{
|
|
||||||
style: 'negative',
|
|
||||||
text: i18n('stickers--StickerManager--Uninstall'),
|
|
||||||
action: handleUninstall,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{i18n('stickers--StickerManager--UninstallWarning')}
|
|
||||||
</ConfirmationDialog>
|
|
||||||
) : (
|
) : (
|
||||||
<div className="module-sticker-manager__preview-modal__container">
|
<Button
|
||||||
<header className="module-sticker-manager__preview-modal__container__header">
|
aria-label={buttonLabel}
|
||||||
<h2 className="module-sticker-manager__preview-modal__container__header__text">
|
ref={focusRef}
|
||||||
{i18n('stickers--StickerPreview--Title')}
|
onClick={handleToggleInstall}
|
||||||
</h2>
|
variant={ButtonVariant.Primary}
|
||||||
<button
|
>
|
||||||
type="button"
|
{buttonLabel}
|
||||||
onClick={closeStickerPackPreview}
|
</Button>
|
||||||
className="module-sticker-manager__preview-modal__container__header__close-button"
|
|
||||||
aria-label={i18n('close')}
|
|
||||||
/>
|
|
||||||
</header>
|
|
||||||
{renderBody(props)}
|
|
||||||
{pack && pack.status !== 'error' ? (
|
|
||||||
<div className="module-sticker-manager__preview-modal__container__meta-overlay">
|
|
||||||
<div className="module-sticker-manager__preview-modal__container__meta-overlay__info">
|
|
||||||
<h3 className="module-sticker-manager__preview-modal__container__meta-overlay__info__title">
|
|
||||||
{pack.title}
|
|
||||||
{pack.isBlessed ? (
|
|
||||||
<span className="module-sticker-manager__preview-modal__container__meta-overlay__info__blessed-icon" />
|
|
||||||
) : null}
|
|
||||||
</h3>
|
|
||||||
<h4 className="module-sticker-manager__preview-modal__container__meta-overlay__info__author">
|
|
||||||
{pack.author}
|
|
||||||
</h4>
|
|
||||||
</div>
|
|
||||||
<div className="module-sticker-manager__preview-modal__container__meta-overlay__install">
|
|
||||||
{pack.status === 'pending' ? (
|
|
||||||
<Spinner svgSize="small" size="14px" />
|
|
||||||
) : (
|
|
||||||
<StickerPackInstallButton
|
|
||||||
ref={focusRef}
|
|
||||||
installed={isInstalled}
|
|
||||||
i18n={i18n}
|
|
||||||
onClick={handleToggleInstall}
|
|
||||||
blue
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>,
|
</div>
|
||||||
root
|
</div>
|
||||||
)
|
) : undefined;
|
||||||
: null;
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{confirmingUninstall && (
|
||||||
|
<ConfirmationDialog
|
||||||
|
dialogName="StickerPreviewModal.confirmUninstall"
|
||||||
|
actions={[
|
||||||
|
{
|
||||||
|
style: 'negative',
|
||||||
|
text: i18n('stickers--StickerManager--Uninstall'),
|
||||||
|
action: handleUninstall,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
i18n={i18n}
|
||||||
|
onClose={() => setConfirmingUninstall(false)}
|
||||||
|
>
|
||||||
|
{i18n('stickers--StickerManager--UninstallWarning')}
|
||||||
|
</ConfirmationDialog>
|
||||||
|
)}
|
||||||
|
<Modal
|
||||||
|
hasXButton
|
||||||
|
i18n={i18n}
|
||||||
|
modalFooter={modalFooter}
|
||||||
|
modalName="StickerPreviewModal"
|
||||||
|
moduleClassName="module-sticker-manager__preview-modal__modal"
|
||||||
|
onClose={handleClose}
|
||||||
|
title={i18n('stickers--StickerPreview--Title')}
|
||||||
|
>
|
||||||
|
{renderBody(props)}
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -142,7 +142,7 @@ describe('storage service', function needsName() {
|
||||||
.click({ noWaitAfter: true });
|
.click({ noWaitAfter: true });
|
||||||
await window
|
await window
|
||||||
.locator(
|
.locator(
|
||||||
'.module-sticker-manager__preview-modal__container button >> "Install"'
|
'.module-sticker-manager__preview-modal__footer--install button >> "Install"'
|
||||||
)
|
)
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
|
@ -186,13 +186,15 @@ describe('storage service', function needsName() {
|
||||||
.click({ noWaitAfter: true });
|
.click({ noWaitAfter: true });
|
||||||
await window
|
await window
|
||||||
.locator(
|
.locator(
|
||||||
'.module-sticker-manager__preview-modal__container button ' +
|
'.module-sticker-manager__preview-modal__footer--install button ' +
|
||||||
'>> "Uninstall"'
|
'>> "Uninstall"'
|
||||||
)
|
)
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
// Confirm
|
// Confirm
|
||||||
await window.locator('.module-Modal button >> "Uninstall"').click();
|
await window
|
||||||
|
.locator('.module-Button--destructive >> "Uninstall"')
|
||||||
|
.click();
|
||||||
|
|
||||||
debug('waiting for sync message');
|
debug('waiting for sync message');
|
||||||
const { syncMessage } = await phone.waitForSyncMessage(entry =>
|
const { syncMessage } = await phone.waitForSyncMessage(entry =>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue