From 8b5b98a5df43a6604bfe4f57dfd5dc848195e2e0 Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Wed, 25 Jul 2018 10:45:13 -0700 Subject: [PATCH 1/7] Build sponsor banner skeleton --- .../widget-settings/SponsorBanner.vue | 29 +++++++++++++++ .../widget-settings/SponsorBanner.vue.ts | 23 ++++++++++++ .../widget-settings/sponsor-banner.ts | 35 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 app/components/widget-settings/SponsorBanner.vue create mode 100644 app/components/widget-settings/SponsorBanner.vue.ts create mode 100644 app/services/widget-settings/sponsor-banner.ts diff --git a/app/components/widget-settings/SponsorBanner.vue b/app/components/widget-settings/SponsorBanner.vue new file mode 100644 index 000000000000..324883a10b0c --- /dev/null +++ b/app/components/widget-settings/SponsorBanner.vue @@ -0,0 +1,29 @@ + + + diff --git a/app/components/widget-settings/SponsorBanner.vue.ts b/app/components/widget-settings/SponsorBanner.vue.ts new file mode 100644 index 000000000000..b9cf73e38652 --- /dev/null +++ b/app/components/widget-settings/SponsorBanner.vue.ts @@ -0,0 +1,23 @@ +import { Component, Prop, Watch } from 'vue-property-decorator'; +import { + SponsorBannerService, + ISponsorBannerData +} from 'services/widget-settings/sponsor-banner'; + +import WidgetWindow from 'components/windows/WidgetWindow.vue'; +import WidgetSettings from './WidgetSettings.vue'; + +import * as comps from 'components/shared/widget-inputs'; +import WFormGroup from 'components/shared/widget-inputs/WFormGroup.vue'; +import { $t } from 'services/i18n'; + +@Component({ + components: { + WidgetWindow, + WFormGroup, + ...comps + } +}) +export default class SponsorBanner extends WidgetSettings { + +} diff --git a/app/services/widget-settings/sponsor-banner.ts b/app/services/widget-settings/sponsor-banner.ts new file mode 100644 index 000000000000..214a0edc39a8 --- /dev/null +++ b/app/services/widget-settings/sponsor-banner.ts @@ -0,0 +1,35 @@ +import { CODE_EDITOR_TABS, IWidgetData, IWidgetSettings, WidgetSettingsService } from './widget-settings'; +import { WidgetType } from 'services/widgets'; +import { metadata } from 'components/shared/widget-inputs/WInput'; + +export interface ISponsorBannerSettings extends IWidgetSettings { + +} + +export interface ISponsorBannerData extends IWidgetData { + settings: ISponsorBannerSettings; +} + +export class SponsorBannerService extends WidgetSettingsService { + + getWidgetType() { + return WidgetType.SponsorBanner; + } + + getVersion() { + return 5; + } + + getPreviewUrl() { + return `https://${ this.getHost() }/widgets/sponsor-banner/v1/${this.getWidgetToken()}?simulate=1`; + } + + getDataUrl() { + return `https://${ this.getHost() }/api/v${ this.getVersion() }/slobs/widget/sponsorbanner`; + } + + protected tabs = [ + { name: 'settings' }, + ...CODE_EDITOR_TABS + ]; +} From b614912a5cbe06585659006e345741f0b2bf9d29 Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Wed, 25 Jul 2018 14:40:24 -0700 Subject: [PATCH 2/7] Build out existing form components --- .../widget-settings/SponsorBanner.vue | 19 ++++++++-- .../widget-settings/SponsorBanner.vue.ts | 2 +- app/services-manager.ts | 2 ++ app/services/sources/sources.ts | 3 +- .../widget-settings/sponsor-banner.ts | 36 +++++++++++++++++-- app/services/windows.ts | 2 ++ 6 files changed, 56 insertions(+), 8 deletions(-) diff --git a/app/components/widget-settings/SponsorBanner.vue b/app/components/widget-settings/SponsorBanner.vue index 324883a10b0c..8c8573d2ffad 100644 --- a/app/components/widget-settings/SponsorBanner.vue +++ b/app/components/widget-settings/SponsorBanner.vue @@ -6,10 +6,24 @@
- {{ JSON.stringify(wData) }} + + + + + + + + + + + + + + + +
-
@@ -22,7 +36,6 @@ - diff --git a/app/components/widget-settings/SponsorBanner.vue.ts b/app/components/widget-settings/SponsorBanner.vue.ts index b9cf73e38652..8525524216d8 100644 --- a/app/components/widget-settings/SponsorBanner.vue.ts +++ b/app/components/widget-settings/SponsorBanner.vue.ts @@ -19,5 +19,5 @@ import { $t } from 'services/i18n'; } }) export default class SponsorBanner extends WidgetSettings { - + placementOptions = [{ title: $t('Single'), value: 'single' }, { title: $t('Double'), value: 'double' }]; } diff --git a/app/services-manager.ts b/app/services-manager.ts index 967cd66f8aa6..2ea68e94dfb3 100644 --- a/app/services-manager.ts +++ b/app/services-manager.ts @@ -87,6 +87,7 @@ import { DonationTickerService } from 'services/widget-settings/donation-ticker' import { CreditsService } from 'services/widget-settings/credits'; import { EventListService } from 'services/widget-settings/event-list'; import { TipJarService } from 'services/widget-settings/tip-jar'; +import { SponsorBannerService } from 'services/widget-settings/sponsor-banner'; const { ipcRenderer } = electron; @@ -174,6 +175,7 @@ export class ServicesManager extends Service { CreditsService, EventListService, TipJarService, + SponsorBannerService, MediaGalleryService }; diff --git a/app/services/sources/sources.ts b/app/services/sources/sources.ts index 7e9124862284..9689db96f071 100644 --- a/app/services/sources/sources.ts +++ b/app/services/sources/sources.ts @@ -390,7 +390,8 @@ export class SourcesService extends StatefulService implements IS WidgetType.Credits, WidgetType.EventList, WidgetType.StreamBoss, - WidgetType.TipJar + WidgetType.TipJar, + WidgetType.SponsorBanner ]; if (isWidget) { diff --git a/app/services/widget-settings/sponsor-banner.ts b/app/services/widget-settings/sponsor-banner.ts index 214a0edc39a8..8ca273bd6778 100644 --- a/app/services/widget-settings/sponsor-banner.ts +++ b/app/services/widget-settings/sponsor-banner.ts @@ -3,7 +3,20 @@ import { WidgetType } from 'services/widgets'; import { metadata } from 'components/shared/widget-inputs/WInput'; export interface ISponsorBannerSettings extends IWidgetSettings { - + background_color_option: boolean; + background_container_color: string; + banner_height: number; + banner_width: number; + hide_duration: number; + hide_duration_secs: number; + image_1_href: string[]; + layout: string; + placement1_durations: number[]; + placement_options: string; + show_animation: string; + show_duration: number; + show_duration_secs: number; + images: { href: string, duration: number }[]; } export interface ISponsorBannerData extends IWidgetData { @@ -21,15 +34,32 @@ export class SponsorBannerService extends WidgetSettingsService /image_\d_href/.test(key)) + .map((key, i) => ({ href: data.settings[key][0], duration: data.settings[`placement${i + 1}_durations`][0] })) + return data; + } + + protected patchBeforeSend(settings: ISponsorBannerSettings): any { + settings.images.forEach((image, i) => { + settings[`image_${i + 1}_href`] = [image.href]; + settings[`placement${i + 1}_durations`] = [image.duration]; + }); + + return settings; + } } diff --git a/app/services/windows.ts b/app/services/windows.ts index 39cbce95c42d..8c6740d56884 100644 --- a/app/services/windows.ts +++ b/app/services/windows.ts @@ -39,6 +39,7 @@ import DonationTicker from 'components/widgets/DonationTicker.vue'; import Credits from 'components/widgets/Credits.vue'; import EventList from 'components/widgets/EventList.vue'; import TipJar from 'components/widgets/TipJar.vue'; +import SponsorBanner from 'components/widgets/SponsorBanner.vue'; const { ipcRenderer, remote } = electron; const BrowserWindow = remote.BrowserWindow; @@ -79,6 +80,7 @@ export function getComponents() { Credits, EventList, TipJar, + SponsorBanner, StreamBoss }; } From d200f7dee8205cb0c6c60d6f100405dc0af671df Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Fri, 27 Jul 2018 10:40:24 -0700 Subject: [PATCH 3/7] Refactor to accept new inputs --- .../widget-settings/SponsorBanner.vue | 42 ------------------ app/components/widgets/SponsorBanner.vue | 42 ++++++++++++++++++ .../SponsorBanner.vue.ts | 10 +++-- .../widget-settings/sponsor-banner.ts | 1 - app/services/widgets/widgets-data.ts | 27 ++++++++++- .../day/source-sponsor-banner.png | Bin 0 -> 5426 bytes .../night/source-sponsor-banner.png | Bin 0 -> 5426 bytes 7 files changed, 74 insertions(+), 48 deletions(-) delete mode 100644 app/components/widget-settings/SponsorBanner.vue create mode 100644 app/components/widgets/SponsorBanner.vue rename app/components/{widget-settings => widgets}/SponsorBanner.vue.ts (72%) create mode 100644 media/source-demos/day/source-sponsor-banner.png create mode 100644 media/source-demos/night/source-sponsor-banner.png diff --git a/app/components/widget-settings/SponsorBanner.vue b/app/components/widget-settings/SponsorBanner.vue deleted file mode 100644 index 8c8573d2ffad..000000000000 --- a/app/components/widget-settings/SponsorBanner.vue +++ /dev/null @@ -1,42 +0,0 @@ - - - diff --git a/app/components/widgets/SponsorBanner.vue b/app/components/widgets/SponsorBanner.vue new file mode 100644 index 000000000000..4666ab405017 --- /dev/null +++ b/app/components/widgets/SponsorBanner.vue @@ -0,0 +1,42 @@ + + + diff --git a/app/components/widget-settings/SponsorBanner.vue.ts b/app/components/widgets/SponsorBanner.vue.ts similarity index 72% rename from app/components/widget-settings/SponsorBanner.vue.ts rename to app/components/widgets/SponsorBanner.vue.ts index 8525524216d8..9f07853d7ca2 100644 --- a/app/components/widget-settings/SponsorBanner.vue.ts +++ b/app/components/widgets/SponsorBanner.vue.ts @@ -7,15 +7,17 @@ import { import WidgetWindow from 'components/windows/WidgetWindow.vue'; import WidgetSettings from './WidgetSettings.vue'; -import * as comps from 'components/shared/widget-inputs'; -import WFormGroup from 'components/shared/widget-inputs/WFormGroup.vue'; +import { inputComponents } from 'components/shared/inputs'; +import { AnimationInput } from './inputs'; +import FormGroup from 'components/shared/inputs/FormGroup.vue'; import { $t } from 'services/i18n'; @Component({ components: { WidgetWindow, - WFormGroup, - ...comps + FormGroup, + AnimationInput, + ...inputComponents } }) export default class SponsorBanner extends WidgetSettings { diff --git a/app/services/widget-settings/sponsor-banner.ts b/app/services/widget-settings/sponsor-banner.ts index 8ca273bd6778..daf75a383e7b 100644 --- a/app/services/widget-settings/sponsor-banner.ts +++ b/app/services/widget-settings/sponsor-banner.ts @@ -1,6 +1,5 @@ import { CODE_EDITOR_TABS, IWidgetData, IWidgetSettings, WidgetSettingsService } from './widget-settings'; import { WidgetType } from 'services/widgets'; -import { metadata } from 'components/shared/widget-inputs/WInput'; export interface ISponsorBannerSettings extends IWidgetSettings { background_color_option: boolean; diff --git a/app/services/widgets/widgets-data.ts b/app/services/widgets/widgets-data.ts index 51de4d92c029..3dd3ddbe3998 100644 --- a/app/services/widgets/widgets-data.ts +++ b/app/services/widgets/widgets-data.ts @@ -16,7 +16,8 @@ export enum WidgetType { ViewerCount = 9, StreamBoss = 10, Credits = 11, - SpinWheel = 12 + SpinWheel = 12, + SponsorBanner = 13 } @@ -274,6 +275,21 @@ export const WidgetDefinitions: { [x: number]: IWidget } = { anchor: AnchorPoint.Center }, + [WidgetType.SponsorBanner]: { + name: 'Sponsor Banner', + url(host, token) { + return `https://${host}/widgets/sponsor-banner?token=${token}`; + }, + + width: 600, + height: 200, + + x: 0, + y: 1, + + anchor: AnchorPoint.SouthWest + }, + [WidgetType.SpinWheel]: { name: 'Spin Wheel', url(host, token) { @@ -408,6 +424,15 @@ export const WidgetDisplayData = (): { [x: number]: IWidgetDisplayData } => ({ $t('Donations') ] }, + [WidgetType.SponsorBanner]: { + name: $t('Sponsor Banner'), + description: $t( + 'Set up a sponsor banner to be able to edit (add, remove, update) rotating sponsor logos on streamer channel.' + ), + demoVideo: false, + demoFilename: 'source-sponsor-banner.png', + supportList: [$t('The streamer manually adds images of sponsors.')] + }, [WidgetType.SpinWheel]: { name: $t('Spin Wheel'), description: $t('Spin the wheel to make a decision.'), diff --git a/media/source-demos/day/source-sponsor-banner.png b/media/source-demos/day/source-sponsor-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..8421d04ff1b70d0d8a34e2450dff8273056a409a GIT binary patch literal 5426 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 literal 0 HcmV?d00001 diff --git a/media/source-demos/night/source-sponsor-banner.png b/media/source-demos/night/source-sponsor-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..8421d04ff1b70d0d8a34e2450dff8273056a409a GIT binary patch literal 5426 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 literal 0 HcmV?d00001 From 22c60ab35bb090e0da273d7bec872975585c576b Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Fri, 3 Aug 2018 11:22:11 -0700 Subject: [PATCH 4/7] Add ImageLayout --- app/components/widgets/SponsorBanner.vue | 3 +++ app/components/widgets/SponsorBanner.vue.ts | 4 +-- app/components/widgets/inputs/ImageLayout.vue | 5 ++++ .../widgets/inputs/ImageLayout.vue.ts | 25 ++++++++++++++++++ app/components/widgets/inputs/inputs.ts | 1 + media/images/layout-image-above.png | Bin 0 -> 15942 bytes media/images/layout-image-side.png | Bin 0 -> 12089 bytes 7 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 app/components/widgets/inputs/ImageLayout.vue create mode 100644 app/components/widgets/inputs/ImageLayout.vue.ts create mode 100644 media/images/layout-image-above.png create mode 100644 media/images/layout-image-side.png diff --git a/app/components/widgets/SponsorBanner.vue b/app/components/widgets/SponsorBanner.vue index 4666ab405017..1436925aa92a 100644 --- a/app/components/widgets/SponsorBanner.vue +++ b/app/components/widgets/SponsorBanner.vue @@ -22,6 +22,9 @@ + + +
diff --git a/app/components/widgets/SponsorBanner.vue.ts b/app/components/widgets/SponsorBanner.vue.ts index 9f07853d7ca2..002226cc83b2 100644 --- a/app/components/widgets/SponsorBanner.vue.ts +++ b/app/components/widgets/SponsorBanner.vue.ts @@ -7,8 +7,7 @@ import { import WidgetWindow from 'components/windows/WidgetWindow.vue'; import WidgetSettings from './WidgetSettings.vue'; -import { inputComponents } from 'components/shared/inputs'; -import { AnimationInput } from './inputs'; +import { inputComponents } from './inputs'; import FormGroup from 'components/shared/inputs/FormGroup.vue'; import { $t } from 'services/i18n'; @@ -16,7 +15,6 @@ import { $t } from 'services/i18n'; components: { WidgetWindow, FormGroup, - AnimationInput, ...inputComponents } }) diff --git a/app/components/widgets/inputs/ImageLayout.vue b/app/components/widgets/inputs/ImageLayout.vue new file mode 100644 index 000000000000..a751ffaddca0 --- /dev/null +++ b/app/components/widgets/inputs/ImageLayout.vue @@ -0,0 +1,5 @@ + + + diff --git a/app/components/widgets/inputs/ImageLayout.vue.ts b/app/components/widgets/inputs/ImageLayout.vue.ts new file mode 100644 index 000000000000..7efbba9d7d2c --- /dev/null +++ b/app/components/widgets/inputs/ImageLayout.vue.ts @@ -0,0 +1,25 @@ +import { Component, Prop } from 'vue-property-decorator'; +import { IListMetadata } from '../../shared/inputs'; +import { BaseInput } from 'components/shared/inputs/BaseInput'; +import ImagePicker from '../../shared/inputs/ImagePicker.vue'; + +@Component({ + components: { ImagePicker } +}) +export default class AnimationInput extends BaseInput> { + + @Prop() + value: string; + + @Prop() + metadata: IListMetadata; + + layoutOptions = [ + { description: './media/images/layout-image-side.png', value: 'side' }, + { description: './media/images/layout-image-above.png', value: 'above'} + ]; + + get meta(): IListMetadata { + return { options: this.layoutOptions, ...this.metadata }; + } +} diff --git a/app/components/widgets/inputs/inputs.ts b/app/components/widgets/inputs/inputs.ts index 9959cdcfbe9f..2c5f2e3e56d4 100644 --- a/app/components/widgets/inputs/inputs.ts +++ b/app/components/widgets/inputs/inputs.ts @@ -1 +1,2 @@ export { default as AnimationInput } from './AnimationInput.vue'; +export { default as ImageLayout } from './ImageLayout.vue'; diff --git a/media/images/layout-image-above.png b/media/images/layout-image-above.png new file mode 100644 index 0000000000000000000000000000000000000000..0a23e831fcb0c87a45fab6307bd539f6209b99f4 GIT binary patch literal 15942 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 literal 0 HcmV?d00001 diff --git a/media/images/layout-image-side.png b/media/images/layout-image-side.png new file mode 100644 index 0000000000000000000000000000000000000000..7842de9ad4777b8ddffa3e3f0e3e29fa5fb0e53d GIT binary patch literal 12089 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 Date: Fri, 3 Aug 2018 14:28:28 -0700 Subject: [PATCH 5/7] Add missing form inputs --- app/components/widgets/SponsorBanner.vue | 49 ++++++++++++++++++- app/components/widgets/SponsorBanner.vue.ts | 22 +++++++++ .../widget-settings/sponsor-banner.ts | 24 +++++---- 3 files changed, 84 insertions(+), 11 deletions(-) diff --git a/app/components/widgets/SponsorBanner.vue b/app/components/widgets/SponsorBanner.vue index 1436925aa92a..1066af07c723 100644 --- a/app/components/widgets/SponsorBanner.vue +++ b/app/components/widgets/SponsorBanner.vue @@ -6,13 +6,26 @@
+ +
+ {{ $t('mins') }} +
+ {{ $t('secs') }} +
+ +
+ {{ $t('mins') }} +
+ {{ $t('secs') }} +
+ - + @@ -25,6 +38,17 @@ + + +
+ + +
{{ $t('Image Duration') }}
+
+ {{ $t('Seconds') }} +
+ +
@@ -43,3 +67,26 @@ + + diff --git a/app/components/widgets/SponsorBanner.vue.ts b/app/components/widgets/SponsorBanner.vue.ts index 002226cc83b2..51f5093047a2 100644 --- a/app/components/widgets/SponsorBanner.vue.ts +++ b/app/components/widgets/SponsorBanner.vue.ts @@ -20,4 +20,26 @@ import { $t } from 'services/i18n'; }) export default class SponsorBanner extends WidgetSettings { placementOptions = [{ title: $t('Single'), value: 'single' }, { title: $t('Double'), value: 'double' }]; + + hideDurationTooltip = $t('Set to zero to show the widget permanently.'); + showDurationTooltip =$t('The amount of time the widget will appear.'); + animationTooltip = $t('These are the animations that are used to show your banner.'); + + get positions() { + return this.wData.settings.placement_options === 'double' ? ['1', '2'] : ['1'] + } + + fileNameFromHref(href: string) { + if (!href) return null; + return decodeURIComponent(href.split(/[\\/]/).pop()); + } + + addImage(placement: string) { + this.wData.settings[`placement_${placement}_images`].push({ href: $t('No Image'), duration: 10 }) + } + + removeImage(href: string, placement: string) { + this.wData.settings[`placement_${placement}_images`] = this.wData.settings[`placement_${placement}_images`] + .filter((image: { href: string }) => image.href !== href); + } } diff --git a/app/services/widget-settings/sponsor-banner.ts b/app/services/widget-settings/sponsor-banner.ts index daf75a383e7b..b83f34f02ee6 100644 --- a/app/services/widget-settings/sponsor-banner.ts +++ b/app/services/widget-settings/sponsor-banner.ts @@ -8,14 +8,17 @@ export interface ISponsorBannerSettings extends IWidgetSettings { banner_width: number; hide_duration: number; hide_duration_secs: number; - image_1_href: string[]; layout: string; - placement1_durations: number[]; placement_options: string; show_animation: string; show_duration: number; show_duration_secs: number; - images: { href: string, duration: number }[]; + image_1_href: string[]; + image_2_href: string[]; + placement1_durations: number[]; + placement2_durations: number[]; + placement_1_images: { href: string, duration: number }[]; + placement_2_images: { href: string, duration: number }[]; } export interface ISponsorBannerData extends IWidgetData { @@ -47,17 +50,18 @@ export class SponsorBannerService extends WidgetSettingsService /image_\d_href/.test(key)) - .map((key, i) => ({ href: data.settings[key][0], duration: data.settings[`placement${i + 1}_durations`][0] })) + data.settings.placement_1_images = data.settings.image_1_href + .map((href: string, i: number) => ({ href: href, duration: data.settings.placement1_durations[i] })) + data.settings.placement_2_images = data.settings.image_2_href + .map((href: string, i: number) => ({ href: href, duration: data.settings.placement2_durations[i] })) return data; } protected patchBeforeSend(settings: ISponsorBannerSettings): any { - settings.images.forEach((image, i) => { - settings[`image_${i + 1}_href`] = [image.href]; - settings[`placement${i + 1}_durations`] = [image.duration]; - }); + settings.image_1_href = settings.placement_1_images.map((image) => image.href); + settings.placement1_durations = settings.placement_1_images.map((image) => image.duration); + settings.image_2_href = settings.placement_2_images.map((image) => image.href); + settings.placement2_durations = settings.placement_2_images.map((image) => image.duration); return settings; } From d663e2898044ff0358e3575709f556b208f3c025 Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Fri, 3 Aug 2018 15:51:47 -0700 Subject: [PATCH 6/7] Fix default image on media gallery --- app/components/shared/inputs/MediaGalleryInput.vue | 2 +- app/components/widgets/SponsorBanner.vue | 2 +- app/services/widget-settings/sponsor-banner.ts | 12 ++++++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/app/components/shared/inputs/MediaGalleryInput.vue b/app/components/shared/inputs/MediaGalleryInput.vue index b6a32223cb12..03c660d56713 100644 --- a/app/components/shared/inputs/MediaGalleryInput.vue +++ b/app/components/shared/inputs/MediaGalleryInput.vue @@ -33,7 +33,7 @@ background-color: @day-secondary; img { - height: 110px; + max-height: 110px; width: auto; position: absolute; top: 50%; diff --git a/app/components/widgets/SponsorBanner.vue b/app/components/widgets/SponsorBanner.vue index 1066af07c723..d5139be19e8e 100644 --- a/app/components/widgets/SponsorBanner.vue +++ b/app/components/widgets/SponsorBanner.vue @@ -39,7 +39,7 @@ - +
diff --git a/app/services/widget-settings/sponsor-banner.ts b/app/services/widget-settings/sponsor-banner.ts index b83f34f02ee6..278809f11b4b 100644 --- a/app/services/widget-settings/sponsor-banner.ts +++ b/app/services/widget-settings/sponsor-banner.ts @@ -51,9 +51,17 @@ export class SponsorBannerService extends WidgetSettingsService ({ href: href, duration: data.settings.placement1_durations[i] })) + .map((href: string, i: number) => { + const subbedHref = href === '/imgs/streamlabs.png' ? + 'https://cdn.streamlabs.com/static/imgs/logos/logo.png' : href; + return ({ href: subbedHref, duration: data.settings.placement1_durations[i] }); + }); data.settings.placement_2_images = data.settings.image_2_href - .map((href: string, i: number) => ({ href: href, duration: data.settings.placement2_durations[i] })) + .map((href: string, i: number) => { + const subbedHref = href === '/imgs/streamlabs.png' ? + 'https://cdn.streamlabs.com/static/imgs/logos/logo.png' : href; + return ({ href: subbedHref, duration: data.settings.placement2_durations[i] }); + }); return data; } From 704971e10af685316d7624e64f252ce3b7310164 Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Fri, 3 Aug 2018 15:58:55 -0700 Subject: [PATCH 7/7] Address CR --- .../shared/inputs/{ImagePicker.vue => ImagePickerInput.vue} | 2 +- .../inputs/{ImagePicker.vue.ts => ImagePickerInput.vue.ts} | 2 +- app/components/shared/inputs/inputs.ts | 2 +- app/components/widgets/SponsorBanner.vue | 2 +- app/components/widgets/TipJar.vue | 2 +- app/components/widgets/inputs/ImageLayout.vue | 5 ----- app/components/widgets/inputs/ImageLayoutInput.vue | 5 +++++ .../inputs/{ImageLayout.vue.ts => ImageLayoutInput.vue.ts} | 6 +++--- app/components/widgets/inputs/inputs.ts | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) rename app/components/shared/inputs/{ImagePicker.vue => ImagePickerInput.vue} (94%) rename app/components/shared/inputs/{ImagePicker.vue.ts => ImagePickerInput.vue.ts} (74%) delete mode 100644 app/components/widgets/inputs/ImageLayout.vue create mode 100644 app/components/widgets/inputs/ImageLayoutInput.vue rename app/components/widgets/inputs/{ImageLayout.vue.ts => ImageLayoutInput.vue.ts} (73%) diff --git a/app/components/shared/inputs/ImagePicker.vue b/app/components/shared/inputs/ImagePickerInput.vue similarity index 94% rename from app/components/shared/inputs/ImagePicker.vue rename to app/components/shared/inputs/ImagePickerInput.vue index 9765179ecc5c..d235deabe777 100644 --- a/app/components/shared/inputs/ImagePicker.vue +++ b/app/components/shared/inputs/ImagePickerInput.vue @@ -12,7 +12,7 @@
- +