Browse Source

adds banner support on the home view

main
Keith Daulton 2 years ago
parent
commit
3ebf9c3539
8 changed files with 176 additions and 4 deletions
  1. +3
    -0
      src/storage.ts
  2. +25
    -0
      src/webviews/apps/home/home.html
  3. +79
    -0
      src/webviews/apps/home/home.scss
  4. +43
    -0
      src/webviews/apps/home/home.ts
  5. BIN
      src/webviews/apps/media/cyber-week-banner-dark.png
  6. BIN
      src/webviews/apps/media/cyber-week-banner-light.png
  7. +20
    -4
      src/webviews/home/homeWebviewView.ts
  8. +6
    -0
      src/webviews/home/protocol.ts

+ 3
- 0
src/storage.ts View File

@ -142,6 +142,9 @@ export interface GlobalStorage {
status: {
pinned?: boolean;
};
banners: {
dismissed?: string[];
};
};
pendingWelcomeOnFocus?: boolean;
pendingWhatsNewOnFocus?: boolean;

+ 25
- 0
src/webviews/apps/home/home.html View File

@ -83,7 +83,32 @@
.gl-plus-banner {
background-image: url(#{webroot}/media/gitlens-backdrop-opacity.webp);
}
.vscode-high-contrast .ribbon-banner,
.vscode-dark .ribbon-banner {
background-image: url(#{webroot}/media/cyber-week-banner-dark.webp);
}
.vscode-high-contrast-light .ribbon-banner,
.vscode-light .ribbon-banner {
background-image: url(#{webroot}/media/cyber-week-banner-light.webp);
}
</style>
<div class="ribbon-banner-container" data-banner="cyberweek2022" hidden>
<a href="#" class="ribbon-banner">
<h2>
<strong>50% off</strong>
<span class="ribbon-banner__subtext">GitLens Pro &amp; all GitKraken products!</span>
</h2>
<p>Expires Dec 5, 2022 11:59pm PT</p>
</a>
<a
href="#"
class="ribbon-banner-dismiss"
data-banner-dismiss="cyberweek2022"
title="Dismiss"
aria-label="Dismiss"
><code-icon icon="close"></code-icon
></a>
</div>
<div class="stepped-sections">
<stepped-section id="welcome">
<span slot="heading">Welcome to GitLens 13</span>

+ 79
- 0
src/webviews/apps/home/home.scss View File

@ -34,6 +34,10 @@
visibility: hidden;
}
[hidden] {
display: none !important;
}
html {
height: 100%;
font-size: 62.5%;
@ -605,6 +609,81 @@ vscode-button {
}
}
.ribbon-banner {
&-container {
position: relative;
}
&-dismiss {
position: absolute;
top: 0;
right: 0;
display: inline-flex;
justify-content: center;
align-items: center;
width: 2.2rem;
height: 2.2rem;
color: var(--color-foreground--75);
&:hover {
color: var(--color-foreground--75);
text-decoration: none;
}
}
.vscode-high-contrast &,
.vscode-dark & {
background-color: var(--color-background--lighten-10);
background-position: right -7rem center;
background-size: auto 140px;
}
.vscode-high-contrast-light &,
.vscode-light & {
background-color: var(--color-background--darken-10);
background-position: right 2.5rem center;
background-size: auto 28px;
}
background-repeat: no-repeat;
display: block;
text-align: left;
color: inherit;
padding: 1.2rem 9.3rem 1.2rem 1.4rem;
line-height: 1.1;
margin-top: -2rem;
margin-bottom: 1rem;
border-radius: 0.4rem;
mix-blend-mode: luminosity;
opacity: 0.8;
transition: opacity ease 250ms, mix-blend-mode ease 250ms;
&:focus,
&:hover {
color: inherit;
text-decoration: none;
mix-blend-mode: normal;
opacity: 1;
}
h2 {
font-size: 1.2rem;
font-weight: inherit;
margin: 0 0 0.8rem 0;
}
p {
font-size: 1rem;
margin: 0;
opacity: 0.8;
}
strong {
font-weight: 800;
opacity: 1;
}
&__subtext {
opacity: 0.8;
}
}
@media (max-width: 280px) {
.not-small {
display: none;

+ 43
- 0
src/webviews/apps/home/home.ts View File

@ -10,6 +10,7 @@ import {
DidChangeExtensionEnabledType,
DidChangeLayoutType,
DidChangeSubscriptionNotificationType,
DismissBannerCommandType,
DismissSectionCommandType,
DismissStatusCommandType,
} from '../../home/protocol';
@ -72,6 +73,9 @@ export class HomeApp extends App {
this.onStatusDismissed(e, target),
),
);
disposables.push(
DOM.on('[data-banner-dismiss]', 'click', (e, target: HTMLElement) => this.onBannerDismissed(e, target)),
);
return disposables;
}
@ -143,6 +147,17 @@ export class HomeApp extends App {
this.updateHeader();
}
private onBannerDismissed(_e: MouseEvent, target: HTMLElement) {
const key = target.getAttribute('data-banner-dismiss');
if (key == null || this.state.dismissedBanners?.includes(key)) {
return;
}
this.state.dismissedBanners = this.state.dismissedBanners ?? [];
this.state.dismissedBanners.push(key);
this.sendCommand(DismissBannerCommandType, { id: key });
this.updateBanners();
}
private onDataActionClicked(_e: MouseEvent, target: HTMLElement) {
const action = target.dataset.action;
this.onActionClickedCore(action);
@ -209,6 +224,28 @@ export class HomeApp extends App {
}
}
private updateBanners() {
const $banners = [...document.querySelectorAll('[data-banner]')];
if (!$banners.length) {
return;
}
const { subscription, dismissedBanners } = this.state;
const isPaid = subscription.state === SubscriptionState.Paid;
$banners.forEach($el => {
const key = $el.getAttribute('data-banner');
if (
isPaid ||
(key !== null && dismissedBanners?.includes(key)) ||
(key === 'cyberweek2022' && !showCyberWeek())
) {
$el.setAttribute('hidden', 'true');
} else {
$el.removeAttribute('hidden');
}
});
}
private updateNoRepo() {
const { extensionEnabled } = this.state;
@ -305,6 +342,7 @@ export class HomeApp extends App {
this.updateSteps(forceShowPlus);
this.updateSections();
this.updateBanners();
}
}
@ -319,4 +357,9 @@ function toggleArrayItem(list: string[] = [], item: string, add = true) {
return list;
}
const cyberweekEnding = Date.parse('2022-12-06T00:00:00.000-08:00');
function showCyberWeek() {
return Date.now() < cyberweekEnding;
}
new HomeApp();

BIN
src/webviews/apps/media/cyber-week-banner-dark.png View File

Before After
Width: 892  |  Height: 260  |  Size: 129 KiB

BIN
src/webviews/apps/media/cyber-week-banner-light.png View File

Before After
Width: 106  |  Height: 56  |  Size: 2.9 KiB

+ 20
- 4
src/webviews/home/homeWebviewView.ts View File

@ -17,7 +17,7 @@ import { debounce } from '../../system/function';
import type { IpcMessage } from '../protocol';
import { onIpc } from '../protocol';
import { WebviewViewBase } from '../webviewViewBase';
import type { CompleteStepParams, DismissSectionParams, State } from './protocol';
import type { CompleteStepParams, DismissBannerParams, DismissSectionParams, State } from './protocol';
import {
CompletedActions,
CompleteStepCommandType,
@ -25,6 +25,7 @@ import {
DidChangeExtensionEnabledType,
DidChangeLayoutType,
DidChangeSubscriptionNotificationType,
DismissBannerCommandType,
DismissSectionCommandType,
DismissStatusCommandType,
} from './protocol';
@ -136,6 +137,9 @@ export class HomeWebviewView extends WebviewViewBase {
case DismissStatusCommandType.method:
onIpc(DismissStatusCommandType, e, _params => this.dismissPinStatus());
break;
case DismissBannerCommandType.method:
onIpc(DismissBannerCommandType, e, params => this.dismissBanner(params));
break;
}
}
@ -153,14 +157,24 @@ export class HomeWebviewView extends WebviewViewBase {
private dismissSection(params: DismissSectionParams) {
const sections = this.container.storage.get('home:sections:dismissed', []);
if (!sections.includes(params.id)) {
sections.push(params.id);
if (sections.includes(params.id)) {
return;
}
sections.push(params.id);
void this.container.storage.store('home:sections:dismissed', sections);
}
private dismissBanner(params: DismissBannerParams) {
const banners = this.container.storage.get('home:banners:dismissed', []);
if (!banners.includes(params.id)) {
banners.push(params.id);
}
void this.container.storage.store('home:banners:dismissed', banners);
}
private dismissPinStatus() {
void this.container.storage.store('home:status:pinned', false);
}
@ -209,6 +223,7 @@ export class HomeWebviewView extends WebviewViewBase {
const subscriptionState = await this.getSubscription(subscription);
const steps = this.container.storage.get('home:steps:completed', []);
const sections = this.container.storage.get('home:sections:dismissed', []);
const dismissedBanners = this.container.storage.get('home:banners:dismissed', []);
return {
extensionEnabled: this.getExtensionEnabled(),
@ -222,6 +237,7 @@ export class HomeWebviewView extends WebviewViewBase {
avatar: subscriptionState.avatar,
layout: this.getLayout(),
pinStatus: this.getPinStatus(),
dismissedBanners: dismissedBanners,
};
}

+ 6
- 0
src/webviews/home/protocol.ts View File

@ -14,6 +14,7 @@ export interface State {
subscription: Subscription;
completedActions: CompletedActions[];
completedSteps?: string[];
dismissedBanners?: string[];
dismissedSections?: string[];
plusEnabled: boolean;
visibility: RepositoriesVisibility;
@ -35,6 +36,11 @@ export const DismissSectionCommandType = new IpcCommandType
export const DismissStatusCommandType = new IpcCommandType<undefined>('home/status/dismiss');
export interface DismissBannerParams {
id: string;
}
export const DismissBannerCommandType = new IpcCommandType<DismissBannerParams>('home/banner/dismiss');
export interface DidChangeSubscriptionParams {
subscription: Subscription;
completedActions: CompletedActions[];

Loading…
Cancel
Save