Skip to content

Commit

Permalink
Merge branch 'release40' into fix/meteor-update
Browse files Browse the repository at this point in the history
  • Loading branch information
nytamin committed Jan 27, 2022
2 parents 8c2f726 + 99a3089 commit 5cc1f12
Show file tree
Hide file tree
Showing 253 changed files with 3,874 additions and 1,167 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Sofie: The Modern TV News Studio Automation System (tv-automation-server-core)
# Sofie: The Modern TV News Studio Automation System (Sofie Core)

This is the "Core" application of the [**Sofie** TV News Studio Automation System](https://github.com/nrkno/Sofie-TV-automation/).

The Core is a Meteor/Node.JS-based web server that serves the web-GUIs as well as handling the business logic for the Sofie TV Automation system.

System documentation can be found here: [Sofie system documentation](https://nrkno.github.io/tv-automation-server-core/).
System documentation can be found here: [Sofie system documentation](https://nrkno.github.io/sofie-core/).

# For developers

Expand All @@ -22,8 +22,8 @@ Follow these instructions to start up Sofie Core in development mode. (For produ
### Quick-start:

```bash
git clone -b master https://github.com/nrkno/tv-automation-server-core.git
cd tv-automation-server-core
git clone -b master https://github.com/nrkno/sofie-core.git
cd sofie-core
yarn start
```

Expand All @@ -34,13 +34,13 @@ yarn start
1. Clone the repository (for development, it is recommended to base your work on the latest unstable release branch)

```bash
git clone -b releaseXYZ https://github.com/nrkno/tv-automation-server-core.git
git clone -b releaseXYZ https://github.com/nrkno/sofie-core.git
```

2. Go into the cloned directory

```bash
cd tv-automation-server-core
cd sofie-core
```

3. Setup meteor and dependencies. (Before this, make sure your NODE_ENV environment variable is NOT set to "production"!)
Expand All @@ -58,7 +58,7 @@ yarn start
5. In another window, start the playout-gateway. You will need to manually restart this upon making changes

```bash
cd tv-automation-server-core/packages/playout-gateway
cd sofie-core/packages/playout-gateway
yarn buildstart
```

Expand Down
122 changes: 122 additions & 0 deletions meteor/CHANGELOG.md

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion meteor/client/lib/userAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Meteor } from 'meteor/meteor'
import { eventContextForLog } from './clientAPI'
import { assertNever } from '../../lib/lib'
import { UserAction } from '../../lib/userAction'
import { translateMessage } from '@sofie-automation/corelib/dist/TranslatableMessage'

export { UserAction }

Expand Down Expand Up @@ -181,7 +182,7 @@ export function doUserAction<Result>(
undefined,
NoticeLevel.CRITICAL,
t('Action {{actionName}} failed: {{error}}', {
error: res.error.message || res.error,
error: translateMessage(res.error.message || res.error, t),
actionName: actionName,
}),
'userAction'
Expand Down
2 changes: 1 addition & 1 deletion meteor/client/styles/contextMenu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ nav.react-contextmenu {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
max-width: 350px;
max-width: 450px;
}

.react-contextmenu-label {
Expand Down
41 changes: 41 additions & 0 deletions meteor/client/ui/SegmentStoryboard/SegmentStoryboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export const SegmentStoryboard = React.memo(
const [listWidth, setListWidth] = useState(0)
const [scrollLeft, setScrollLeft] = useState(0)
const [grabbed, setGrabbed] = useState<{ clientX: number; clientY: number } | null>(null)
const [touched, setTouched] = useState<{ clientX: number; clientY: number } | null>(null)
const [animateScrollLeft, setAnimateScrollLeft] = useState(true)
const { t } = useTranslation()
const notes: Array<SegmentNote> = props.segmentNotes
Expand Down Expand Up @@ -389,6 +390,12 @@ export const SegmentStoryboard = React.memo(
clientY: e.clientY,
})
setAnimateScrollLeft(false)
} else if ((e.pointerType === 'touch' && e.isPrimary) || (e.pointerType === 'pen' && e.isPrimary)) {
setTouched({
clientX: e.clientX,
clientY: e.clientY,
})
setAnimateScrollLeft(false)
}
}

Expand Down Expand Up @@ -459,6 +466,40 @@ export const SegmentStoryboard = React.memo(
}
}, [grabbed, renderedParts.length, props.onScroll])

useEffect(() => {
if (!touched) return

const startingScrollLeft = scrollLeft

const onListTouchRelease = () => {
setTouched(null)
setAnimateScrollLeft(true)
}
const onTouchMove = (e: TouchEvent) => {
e.preventDefault()
setScrollLeft(() => {
const newScrollLeft = Math.max(
0,
Math.min(startingScrollLeft + (touched.clientX - e.touches[0].clientX), maxScrollLeft)
)
props.onScroll(newScrollLeft, e)
return newScrollLeft
})
}

document.addEventListener('touchend', onListTouchRelease)
document.addEventListener('touchcancel', onListTouchRelease)
document.addEventListener('touchmove', onTouchMove, {
passive: false,
})

return () => {
document.removeEventListener('touchend', onListTouchRelease)
document.removeEventListener('touchcancel', onListTouchRelease)
document.removeEventListener('touchmove', onTouchMove)
}
}, [touched, renderedParts.length, props.onScroll])

useLayoutEffect(() => {
const segment = innerRef.current
if (!segment) return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@ export function LocalThumbnailRenderer({ pieceInstance }: IProps) {
<div className="segment-storyboard__thumbnail__label segment-storyboard__thumbnail__label--lg">
{color && (
<span
style={{ color: color.startsWith('#') ? color : `#${color}` }}
className="segment-timeline__piece__label segment-timeline__piece__label__colored-mark"
style={{ backgroundColor: color.startsWith('#') ? color : `#${color}` }}
className="segment-storyboard__thumbnail__label segment-storyboard__thumbnail__label__colored-mark"
>
·
</span>
)}
{localContent.studioLabel
? `${pieceInstance.sourceLayer?.abbreviation}${localContent.studioLabel}` || pieceInstance.instance.piece.name
: pieceInstance.instance.piece.name}
{pieceInstance.instance.piece.name}
</div>
</>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,26 +89,26 @@ export function VTThumbnailRenderer({
<RundownTimingConsumer
filter={(timingContext) => ({
partPlayed: timingContext.partPlayed && timingContext.partPlayed[unprotectString(partId)],
partExpectedDuration:
timingContext.partExpectedDurations && timingContext.partExpectedDurations[unprotectString(partId)],
partDisplayDurations:
timingContext.partDisplayDurations && timingContext.partDisplayDurations[unprotectString(partId)],
})}
>
{(timingContext) => {
if (!timingContext.partPlayed || !timingContext.partExpectedDurations) return null
if (!timingContext.partPlayed || !timingContext.partDisplayDurations) return null

const partPlayed = timingContext.partPlayed[unprotectString(partId)] ?? 0
const contentEnd =
(vtContent?.sourceDuration ?? 0) - (vtContent?.seek ?? 0) + (pieceInstance.renderedInPoint ?? 0)

const contentLeft =
(vtContent?.sourceDuration ?? 0) -
(vtContent?.seek ?? 0) +
(pieceInstance.renderedInPoint ?? 0) -
partPlayed
const contentLeft = contentEnd - partPlayed

const partLeft = timingContext.partExpectedDurations[unprotectString(partId)] - partPlayed
const partExpectedDuration = timingContext.partDisplayDurations[unprotectString(partId)]

const partLeft = partExpectedDuration - partPlayed

return !isFinished &&
!(hovering && thumbnailUrl && previewUrl) &&
contentLeft < 10000 &&
(contentLeft < 10000 || contentEnd < partExpectedDuration) &&
(!partAutoNext || partLeft > contentLeft) ? (
<div
className={classNames('segment-storyboard__thumbnail__countdown', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,19 @@
font-size: 0.85em;
letter-spacing: normal;
}

> .segment-storyboard__thumbnail__label__colored-mark {
font-size: 1em;
color: transparent;
display: inline-block;
height: 0.8em;
width: 0.8em;
border-radius: 100%;
margin-right: 0.5em;
vertical-align: middle;
box-shadow: 0 0 6px rgba(0, 0, 0, 1);
margin-top: -0.1em;
}
}

> .segment-storyboard__thumbnail__countdown {
Expand Down
1 change: 0 additions & 1 deletion meteor/client/ui/SegmentTimeline/SegmentTimeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,6 @@ export class SegmentTimelineClass extends React.Component<Translated<IProps>, IS
) : null}
</div>
</div>
,
</>
)
}
Expand Down
2 changes: 1 addition & 1 deletion meteor/client/ui/Shelf/DashboardPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export function dashboardElementStyle(el: DashboardPositionableElement): React.C
: el.height < 0
? `calc(${-1 * el.height - 1} * var(--dashboard-button-grid-height))`
: undefined,
fontSize: (el.scale || 1) * 1.5 + 'em',
fontSize: el.scale ? el.scale * 1.5 + 'em' : undefined,
}
}

Expand Down
4 changes: 4 additions & 0 deletions meteor/lib/Rundown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,10 @@ export function sortAdlibs<T>(
if (a.partRank > b.partRank) return 1
if (a.partRank < b.partRank) return -1

// Sort by adlib rank
if (a.adlibRank > b.adlibRank) return 1
if (a.adlibRank < b.adlibRank) return -1

// Sort by labels:
const r = compareLabels(a.label, b.label)
if (r !== 0) return r
Expand Down
2 changes: 1 addition & 1 deletion meteor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,4 @@
"postbump": "npm run libs:syncVersionsAndChangelogs"
}
}
}
}
8 changes: 4 additions & 4 deletions meteor/server/api/blueprints/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from '@sofie-automation/blueprints-integration'
import { check, Match } from '../../../lib/check'
import { NewBlueprintAPI, BlueprintAPIMethods } from '../../../lib/api/blueprint'
import { registerClassToMeteorMethods } from '../../methods'
import { registerClassToMeteorMethods, ReplaceOptionalWithNullInMethodArguments } from '../../methods'
import { parseVersion, CoreSystem, SYSTEM_ID, getCoreSystem } from '../../../lib/collections/CoreSystem'
import { evalBlueprint } from './cache'
import { removeSystemStatus } from '../../systemStatus/systemStatus'
Expand Down Expand Up @@ -248,7 +248,7 @@ export async function innerUploadBlueprint(
return newBlueprint
}

async function assignSystemBlueprint(methodContext: MethodContext, blueprintId?: BlueprintId): Promise<void> {
async function assignSystemBlueprint(methodContext: MethodContext, blueprintId: BlueprintId | null): Promise<void> {
SystemWriteAccess.coreSystem(methodContext)

if (blueprintId !== undefined && blueprintId !== null) {
Expand Down Expand Up @@ -280,14 +280,14 @@ async function assignSystemBlueprint(methodContext: MethodContext, blueprintId?:
}
}

class ServerBlueprintAPI extends MethodContextAPI implements NewBlueprintAPI {
class ServerBlueprintAPI extends MethodContextAPI implements ReplaceOptionalWithNullInMethodArguments<NewBlueprintAPI> {
async insertBlueprint() {
return insertBlueprint(this)
}
async removeBlueprint(blueprintId: BlueprintId) {
return removeBlueprint(this, blueprintId)
}
async assignSystemBlueprint(blueprintId?: BlueprintId) {
async assignSystemBlueprint(blueprintId: BlueprintId | null) {
return assignSystemBlueprint(this, blueprintId)
}
}
Expand Down
Loading

0 comments on commit 5cc1f12

Please sign in to comment.