+
+ {openedFrom === 'after-stream' ? 'Ai Highlighter' : `${$t('Import Game Recording')}`}
+
{' '}
+
+
-
-
-
- {openedFrom === 'after-stream' ? 'Ai Highlighter' : `${$t('Import Game Recording')}`}
-
{' '}
-
-
-
-
+
-
-
{
- const path = await importStreamFromDevice();
- setFilePath(path ? path[0] : undefined);
- }}
- onDragOver={e => {
- e.preventDefault();
- setDraggingOver(true);
- }}
- onDrop={e => {
- const extensions = SUPPORTED_FILE_TYPES.map(e => `.${e}`);
- const files: string[] = [];
- let fi = e.dataTransfer.files.length;
- while (fi--) {
- const file = e.dataTransfer.files.item(fi)?.path;
- if (file) files.push(file);
- }
- const filtered = files.filter(f => extensions.includes(path.parse(f).ext));
- if (filtered.length) {
- setFilePath(filtered[0]);
- setDraggingOver(false);
- }
+
+
{
+ const path = await importStreamFromDevice();
+ setFilePath(path ? path[0] : undefined);
+ }}
+ onDragOver={e => {
+ e.preventDefault();
+ setDraggingOver(true);
+ }}
+ onDrop={e => {
+ const extensions = SUPPORTED_FILE_TYPES.map(e => `.${e}`);
+ const files: string[] = [];
+ let fi = e.dataTransfer.files.length;
+ while (fi--) {
+ const file = e.dataTransfer.files.item(fi)?.path;
+ if (file) files.push(file);
+ }
+ const filtered = files.filter(f => extensions.includes(path.parse(f).ext));
+ if (filtered.length) {
+ setFilePath(filtered[0]);
+ setDraggingOver(false);
+ }
- e.preventDefault();
- e.stopPropagation();
- }}
- onDragLeave={() => setDraggingOver(false)}
- className={styles.videoPreview}
- style={
- {
- '--border-style': filePath ? 'solid' : 'dashed',
- '--border-color': draggingOver ? 'var(--teal)' : 'var(--midtone)',
- cursor: 'pointer',
- } as React.CSSProperties
- }
+ e.preventDefault();
+ e.stopPropagation();
+ }}
+ onDragLeave={() => setDraggingOver(false)}
+ className={styles.videoPreview}
+ style={
+ {
+ '--border-style': filePath ? 'solid' : 'dashed',
+ '--border-color': draggingOver ? 'var(--teal)' : 'var(--midtone)',
+ cursor: 'pointer',
+ } as React.CSSProperties
+ }
+ >
+ {filePath ? (
+
+ ) : (
+
) => {}}
+ style={{ display: 'grid', placeItems: 'center' }}
>
- {filePath ? (
-
- ) : (
-
) => {}}
- style={{ display: 'grid', placeItems: 'center' }}
- >
-
-
- {$t('Drag and drop game recording or click to select')}
-
-
- )}
-
-
-
-
- {openedFrom === 'after-stream' && (
-
- )}
-
-
+ {$t('Drag and drop game recording or click to select')}
+
-
+ )}
- >
- );
-}
-
-export function YouTubeLogo() {
- return (
-
- );
-}
-
-export function DiscordLogo() {
- return (
-
- );
-}
+
-export function TikTokLogo() {
- return (
-
- );
-}
+
+ {openedFrom === 'after-stream' && (
+
+ )}
-export function InstagramLogo() {
- return (
-
+ {filePath ? $t('Find game highlights') : $t('Select video and start import')}
+
+
+
+ {replayInstalled ? (
+
Continuing will open Streamlabs Highlighter
+ ) : (
+
Continuing will install Streamlabs Highlighter
+ )}
+
+
);
}
diff --git a/app/components-react/highlighter/StreamView.m.less b/app/components-react/highlighter/StreamView.m.less
index 9a07422a6418..ad4e57e30bad 100644
--- a/app/components-react/highlighter/StreamView.m.less
+++ b/app/components-react/highlighter/StreamView.m.less
@@ -12,6 +12,9 @@
:global(.ant-modal-wrap),
:global(.ant-modal-mask) {
position: absolute;
+ top: 0 !important;
+ height: 100% !important;
+ overflow: hidden !important;
}
:global(.os-content-glue) {
@@ -33,6 +36,9 @@
:global(.ant-modal-wrap),
:global(.ant-modal-mask) {
position: absolute;
+ top: 0 !important;
+ height: 100% !important;
+ overflow: hidden !important;
}
:global(.os-content-glue) {
@@ -62,6 +68,13 @@
.stream-card-modal-root {
position: relative;
+ :global(.ant-modal-wrap),
+ :global(.ant-modal-mask) {
+ position: absolute;
+ top: 0 !important;
+ height: 100% !important;
+ overflow: hidden !important;
+ }
}
// Upload
@@ -81,8 +94,9 @@
--fixed-height: 504px;
--fixed-width: 441px;
position: relative;
- width: 80vw;
height: 80vh;
+ width: 80vw;
+ max-width: 1500px;
display: grid;
border-radius: 24px;
overflow: hidden;
@@ -253,6 +267,7 @@
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
+ height: 556px; // needs to be hardcoded. to match hypewrapper
:global {
/* Hide labels */
@@ -370,3 +385,14 @@
object-fit: cover;
border-radius: 1px;
}
+
+.explainer-text-wrapper {
+ display: flex;
+ justify-content: center;
+}
+
+.explainer-text {
+ opacity: 60%;
+ text-align: center;
+ width: 100%;
+}
diff --git a/app/components-react/highlighter/StreamView.tsx b/app/components-react/highlighter/StreamView.tsx
index b7ff83116154..8bbca0c581c3 100644
--- a/app/components-react/highlighter/StreamView.tsx
+++ b/app/components-react/highlighter/StreamView.tsx
@@ -26,6 +26,8 @@ import EducationCarousel from './EducationCarousel';
import { EGame } from 'services/highlighter/models/ai-highlighter.models';
import { ImportStreamModal } from './ImportStream';
import SupportedGames from './supportedGames/SupportedGames';
+import MigrationNotice from './migration/MigrationNotice';
+import { EAvailableFeatures } from 'services/incremental-rollout';
type TModalStreamView = {
type: 'upload';
@@ -36,7 +38,12 @@ type TModalStreamView = {
} | null;
export default function StreamView({ emitSetView }: { emitSetView: (data: IViewState) => void }) {
- const { HighlighterService, HotkeysService, UsageStatisticsService } = Services;
+ const {
+ HighlighterService,
+ HotkeysService,
+ UsageStatisticsService,
+ IncrementalRolloutService,
+ } = Services;
const v = useVuex(() => ({
error: HighlighterService.views.error,
uploadInfo: HighlighterService.views.uploadInfo,
@@ -44,6 +51,10 @@ export default function StreamView({ emitSetView }: { emitSetView: (data: IViewS
tempRecordingInfoPath: HighlighterService.views.tempRecordingInfo.recordingPath,
}));
+ const migrationEnabled = IncrementalRolloutService.views.featureIsEnabled(
+ EAvailableFeatures.highlighterMigration,
+ );
+
useEffect(() => {
const recordingInfo = { ...HighlighterService.views.tempRecordingInfo };
HighlighterService.setTempRecordingInfo({});
@@ -169,6 +180,14 @@ export default function StreamView({ emitSetView }: { emitSetView: (data: IViewS