Skip to content

Commit

Permalink
🕐 Slide progress tracker item
Browse files Browse the repository at this point in the history
- Stage progress bar
- Fixed stage output loop
- Scripture style template will also override created shows
- Some dynamic values working in stage output
- Opening edit section tabs will no longer apply preset styles to reduce confusion
- Fixed edit values not always resetting
  • Loading branch information
vassbo committed Jul 24, 2024
1 parent 865c303 commit 74ff21e
Show file tree
Hide file tree
Showing 32 changed files with 666 additions and 350 deletions.
6 changes: 5 additions & 1 deletion public/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,7 @@
"_title_underline": "Underline",
"_title_strikethrough": "Strikethrough",
"color": "Color",
"accent_color": "Accent color",
"background_color": "Background color",
"background_opacity": "Background opacity",
"background_image": "Background image",
Expand Down Expand Up @@ -768,7 +769,8 @@
"start_days_from_today": "Start at days from today",
"just_one_day": "Just one day",
"enable_start_date": "Enable start date",
"disable_navigation": "Disable navigation controls"
"disable_navigation": "Disable navigation controls",
"progress_bar": "Progress bar"
},
"items": {
"text": "Textbox",
Expand All @@ -785,6 +787,7 @@
"timer": "Timer",
"variable": "Variable",
"web": "Website",
"slide_tracker": "Progress",
"visualizer": "Visualizer",
"captions": "Captions",
"icon": "Icon"
Expand Down Expand Up @@ -890,6 +893,7 @@
"next_slide_notes": "Next slide notes",
"output": "Output",
"current_output": "Current output",
"slide_tracker": "Progress",
"time": "Time",
"system_clock": "System clock",
"video_time": "Video time",
Expand Down
6 changes: 3 additions & 3 deletions src/electron/capture/helpers/CaptureTransmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ export class CaptureTransmitter {
return image
}

static sendToStageOutputs(msg: any) {
;[...new Set(this.stageWindows)].forEach((id) => OutputHelper.Send.sendToWindow(id, msg))
static sendToStageOutputs(msg: any, excludeId: string = "") {
;[...new Set(this.stageWindows)].forEach((id) => id !== excludeId && OutputHelper.Send.sendToWindow(id, msg))
}

static sendToRequested(msg: any) {
Expand Down Expand Up @@ -143,7 +143,7 @@ export class CaptureTransmitter {

let msg = { channel: "BUFFER", data: { id: captureId, buffer, size } }
toApp(OUTPUT, msg)
this.sendToStageOutputs(msg)
this.sendToStageOutputs(msg, captureId) // don't send to itself
this.sendToRequested(msg)
}

Expand Down
2 changes: 1 addition & 1 deletion src/electron/output/helpers/OutputLifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class OutputLifecycle {

//OutputHelper.Bounds.updatePreviewBounds()

if (output.stageOutput) CaptureHelper.Transmitter.stageWindows.push(id)
if (output.stageOutput && !CaptureHelper.Transmitter.stageWindows.includes(id)) CaptureHelper.Transmitter.stageWindows.push(id)

setTimeout(() => {
CaptureHelper.Lifecycle.startCapture(id, { ndi: output.ndi || false })
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/MainOutput.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

<div
class="fill context #output_window"
style="flex-direction: {getStyleResolution(resolution, width, height, 'fit').includes('width') && !Object.values($outputs)[0].stageOutput ? 'row' : 'column'}"
style="flex-direction: {getStyleResolution(resolution, width, height, 'fit').includes('width') && !Object.values($outputs)[0]?.stageOutput ? 'row' : 'column'}"
class:hideCursor={$special.hideCursor}
on:mousemove={mousemoveOutput}
bind:offsetWidth={width}
Expand Down
7 changes: 5 additions & 2 deletions src/frontend/components/actions/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export function customActionActivation(id: string) {
})
}

export function addSlideAction(slideIndex: number, actionId: string, actionValue: any = {}) {
export function addSlideAction(slideIndex: number, actionId: string, actionValue: any = {}, allowMultiple: boolean = false) {
if (slideIndex < 0) return

let ref = _show().layouts("active").ref()[0]
Expand All @@ -98,7 +98,10 @@ export function addSlideAction(slideIndex: number, actionId: string, actionValue
if (actionValue) actionValues[actionId] = actionValue

let action = { id, triggers: [actionId], actionValues }
actions.slideActions.push(action)

let existingIndex = actions.slideActions.findIndex((a) => a.triggers?.[0] === actionId)
if (allowMultiple || existingIndex < 0) actions.slideActions.push(action)
else actions.slideActions[existingIndex] = action

history({ id: "SHOW_LAYOUT", newData: { key: "actions", data: actions, indexes: [slideIndex] } })
}
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/components/drawer/bible/scripture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export const textKeys = {
export function getSlides({ bibles, sorted }) {
let slides: any[][] = [[]]

let template = get(templates)[get(scriptureSettings).template]?.items || []
let template = clone(get(templates)[get(scriptureSettings).template]?.items || [])
let templateTextItems = template.filter((a) => a.lines)
let templateOtherItems = template.filter((a) => !a.lines && a.type !== "text")

Expand Down
2 changes: 1 addition & 1 deletion src/frontend/components/drawer/pages/Templates.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
templates.subscribe(updateTemplates)
function updateTemplates() {
filteredTemplates = Object.keys($templates)
filteredTemplates = clone(Object.keys($templates))
.map((id) => ({ id, ...$templates[id] }))
.filter((s: any) => active === "all" || active === s.category || (active === "unlabeled" && (s.category === null || !$templateCategories[s.category])))
.sort((a, b) => a.name.localeCompare(b.name))
Expand Down
266 changes: 131 additions & 135 deletions src/frontend/components/edit/editbox/EditboxHelper.ts
Original file line number Diff line number Diff line change
@@ -1,149 +1,145 @@
import type { Item, Line } from "../../../../types/Show"

export class EditboxHelper {
//Compare text of all the new lines to determine if it's truly a modification or just an index change.
//Set the cursor to the start of the last line that was modified.
static determineCaretLine(oldLines: Line[], newLines: Line[]) {
const oldTexts: string[] = []
const newTexts: string[] = []

oldLines?.forEach((line) => {
oldTexts.push(line.text[0].value)
})

newLines.forEach((line) => {
newTexts.push(line.text[0].value)
})


//Compare text of all the new lines to determine if it's truly a modification or just an index change.
//Set the cursor to the start of the last line that was modified.
static determineCaretLine(oldLines:Line[], newLines: Line[]) {
const oldTexts:string[] = [];
const newTexts:string[] = [];

oldLines?.forEach((line) => {
oldTexts.push(line.text[0].value);
});

newLines.forEach((line) => {
newTexts.push(line.text[0].value);
});

let lastLineChanged = -1;
if (oldTexts.length === newTexts.length) return lastLineChanged;
for (let i=0; i<newTexts.length; i++) {
const nt = newTexts[i];
const index = oldTexts.indexOf(nt);
if (index === -1) lastLineChanged = i;
else oldTexts.splice(index, 1);
let lastLineChanged = -1
if (oldTexts.length === newTexts.length) return lastLineChanged
for (let i = 0; i < newTexts.length; i++) {
const nt = newTexts[i]
const index = oldTexts.indexOf(nt)
if (index === -1) lastLineChanged = i
else oldTexts.splice(index, 1)
}
return lastLineChanged
}

static splitAllCrlf(lines: Line[]) {
let result: Line[] = []
lines.forEach((line) => {
let splitLines = this.splitCrlf(line)
result.push(...splitLines)
})
return result
}
return lastLineChanged;
}

static splitAllCrlf(lines: Line[]) {
let result: Line[] = []
lines.forEach((line) => {
let splitLines = this.splitCrlf(line)
result.push(...splitLines)
})
return result
}

static splitCrlf(line: Line) {
const result: Line[] = []
let newLine = { ...line }
newLine.text = []

line.text.forEach((text) => {
let value = text.value
let parts = value.replace("\r", "").split("\n")
newLine.text.push({ style: text.style, value: parts[0] })
if (parts.length > 1) {
for (let i = 1; i < parts.length; i++) {
result.push(newLine)
newLine = { ...line }
newLine.text = [{ style: text.style, value: parts[i] }]

static splitCrlf(line: Line) {
const result: Line[] = []
let newLine = { ...line }
newLine.text = []

line.text.forEach((text) => {
let value = text.value
let parts = value.replace("\r", "").split("\n")
newLine.text.push({ style: text.style, value: parts[0] })
if (parts.length > 1) {
for (let i = 1; i < parts.length; i++) {
result.push(newLine)
newLine = { ...line }
newLine.text = [{ style: text.style, value: parts[i] }]
}
}
}
})
result.push(newLine)
return result
}

static cutLinesInTwo({ sel, lines, currentIndex, textPos, start }) {
let firstLines: Line[] = []
let secondLines: Line[] = []

lines.forEach((line:Line, i:number) => {
if (start > -1 && currentIndex >= start) secondLines.push({ align: line.align, text: [] })
else firstLines.push({ align: line.align, text: [] })

textPos = 0
line.text?.forEach((text) => {
currentIndex += text.value.length
if (sel[i]?.start !== undefined) start = sel[i].start

if (start > -1 && currentIndex >= start) {
if (!secondLines.length) secondLines.push({ align: line.align, text: [] })
let pos = sel[i].start - textPos
if (pos > 0)
})
result.push(newLine)
return result
}

static cutLinesInTwo({ sel, lines, currentIndex, textPos, start }) {
let firstLines: Line[] = []
let secondLines: Line[] = []

lines.forEach((line: Line, i: number) => {
if (start > -1 && currentIndex >= start) secondLines.push({ align: line.align, text: [] })
else firstLines.push({ align: line.align, text: [] })

textPos = 0
line.text?.forEach((text) => {
currentIndex += text.value.length
if (sel[i]?.start !== undefined) start = sel[i].start

if (start > -1 && currentIndex >= start) {
if (!secondLines.length) secondLines.push({ align: line.align, text: [] })
let pos = sel[i].start - textPos
if (pos > 0)
firstLines[firstLines.length - 1].text.push({
style: text.style,
value: text.value.slice(0, pos),
})
secondLines[secondLines.length - 1].text.push({
style: text.style,
value: text.value.slice(pos, text.value.length),
})
} else {
firstLines[firstLines.length - 1].text.push({
style: text.style,
value: text.value.slice(0, pos),
value: text.value,
})
secondLines[secondLines.length - 1].text.push({
style: text.style,
value: text.value.slice(pos, text.value.length),
})
} else {
firstLines[firstLines.length - 1].text.push({
style: text.style,
value: text.value,
})
}
textPos += text.value.length
})
}
textPos += text.value.length
})

if (!firstLines.at(-1)?.text.length) firstLines.pop()
})

let defaultLine = [
{
align: lines[0].align || "",
text: [{ style: lines[0].text[0]?.style || "", value: "" }],
},
]
if (!firstLines.length || !firstLines[0].text.length) firstLines = defaultLine
if (!secondLines.length) secondLines = defaultLine
return {firstLines, secondLines}
}

static getSyleHtml(item:Item, plain:boolean, currentStyle:string) {
let html = ""
let firstTextStyleArchive: string = ""
let lineBg = item.specialStyle?.lineBg ? `background-color: ${item.specialStyle.lineBg};` : ""
item?.lines?.forEach((line, i) => {
let align = line.align.replaceAll(lineBg, "")
currentStyle += align + lineBg
let style = align || lineBg ? 'style="' + align + lineBg + '"' : ""
html += `<div class="break" ${plain ? "" : style}>`

// fix removing all text in a line
if (i === 0 && line.text?.[0]?.style) firstTextStyleArchive = line.text?.[0]?.style || ""
if (!line.text?.length) line.text = [{ style: firstTextStyleArchive || "", value: "" }]

let currentChords = line.chords || []
let textIndex = 0

line.text?.forEach((a, tIndex) => {
currentStyle += this.getTextStyle(a)

// SAVE CHORDS (WIP does not work well with more "text" per line)
let textEnd = textIndex + a.value.length
let textChords = currentChords.filter((a) => a.pos >= textIndex && (a.pos <= textEnd || line.text.length - 1 >= tIndex))
textIndex = textEnd

let style = a.style ? 'style="' + a.style + '"' : ""

html += `<span class="${a.customType ? "custom" : ""}" ${plain ? "" : style} data-chords='${JSON.stringify(textChords)}'>` + (a.value.replaceAll("\n", "<br>") || "<br>") + "</span>"
if (!firstLines.at(-1)?.text.length) firstLines.pop()
})
html += "</div>"
})
return {html, currentStyle};
}

static getTextStyle(lineText:any) {
let style = lineText.style || ""
return style
}
let defaultLine = [
{
align: lines[0].align || "",
text: [{ style: lines[0].text[0]?.style || "", value: "" }],
},
]
if (!firstLines.length || !firstLines[0].text.length) firstLines = defaultLine
if (!secondLines.length) secondLines = defaultLine
return { firstLines, secondLines }
}

static getSyleHtml(item: Item, plain: boolean, currentStyle: string) {
let html = ""
let firstTextStyleArchive: string = ""
let lineBg = item.specialStyle?.lineBg ? `background-color: ${item.specialStyle.lineBg};` : ""
item?.lines?.forEach((line, i) => {
let align = line.align.replaceAll(lineBg, "")
currentStyle += align + lineBg
let style = align || lineBg ? 'style="' + align + ";" + lineBg + '"' : ""
html += `<div class="break" ${plain ? "" : style}>`

// fix removing all text in a line
if (i === 0 && line.text?.[0]?.style) firstTextStyleArchive = line.text?.[0]?.style || ""
if (!line.text?.length) line.text = [{ style: firstTextStyleArchive || "", value: "" }]

let currentChords = line.chords || []
let textIndex = 0

line.text?.forEach((a, tIndex) => {
currentStyle += this.getTextStyle(a)

}
// SAVE CHORDS (WIP does not work well with more "text" per line)
let textEnd = textIndex + a.value.length
let textChords = currentChords.filter((a) => a.pos >= textIndex && (a.pos <= textEnd || line.text.length - 1 >= tIndex))
textIndex = textEnd

let style = a.style ? 'style="' + a.style + '"' : ""

html += `<span class="${a.customType ? "custom" : ""}" ${plain ? "" : style} data-chords='${JSON.stringify(textChords)}'>` + (a.value.replaceAll("\n", "<br>") || "<br>") + "</span>"
})
html += "</div>"
})
return { html, currentStyle }
}

static getTextStyle(lineText: any) {
let style = lineText.style || ""
return style
}
}
Loading

0 comments on commit 74ff21e

Please sign in to comment.