Skip to content

Commit

Permalink
feat(webinterface): add Trendmark advanced settings (#139)
Browse files Browse the repository at this point in the history
  • Loading branch information
mhellmeier authored Nov 28, 2024
1 parent 5b7f671 commit 9e6fb05
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 11 deletions.
2 changes: 1 addition & 1 deletion docs/docs/03-usage/11-cli/01-installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Use Gradle to build the CLI tool:
*Note:* You must replace `<version>` in the following commands (e.g. `0.1.0-SNAPSHOT`)

1. `cd cli` (if not already there)
2. `./gradlew shadowJar"`
2. `./gradlew shadowJar`
- This will create a standalone jar file: `./build/libs/cli-<version>-all.jar`
3. `java -jar build/libs/cli-<version>-all.jar --help`
- This will print all possible commands of the CLI tool.
Expand Down
6 changes: 6 additions & 0 deletions docs/docs/03-usage/12-webinterface/01-installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ the following commands from the root directory of the project:
1. `cd watermarker`
2. `./gradlew publishToMavenLocal`

:::info
The source code comes with enabled source maps to allow frontend debugging. They should be disabled
in production to prevent the exposure of source code. To disable it, add `sourceMaps = false` inside
the `build.gradle.kts`.
:::

## Building from Source (Manual Build)

Use Gradle to manually build and run the webinterface:
Expand Down
17 changes: 17 additions & 0 deletions watermarker/src/commonTest/kotlin/unitTest/WatermarkerTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package unitTest

import Platform
import de.fraunhofer.isst.trend.watermarker.SupportedFileType
import de.fraunhofer.isst.trend.watermarker.Watermarker
import de.fraunhofer.isst.trend.watermarker.fileWatermarker.DefaultTranscoding
Expand Down Expand Up @@ -167,6 +168,22 @@ class WatermarkerTest {
assertEquals(expected, result.value)
}

@Test
fun textGetWatermarks_exactlyOneWatermark_successAndWatermark() {
// Arrange
val expected =
listOf(
Watermark.fromString("a"),
)

// Act
val result = watermarker.textGetWatermarks("a a a a a a a a a a")

// Assert
assertTrue(result.isSuccess)
assertEquals(expected, result.value)
}

@Test
fun textGetWatermarks_differentWatermarks_successAndNotSquashedWatermarks() {
// Arrange
Expand Down
1 change: 0 additions & 1 deletion webinterface/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ kotlin {
runTask(
Action {
mainOutputFileName = "main.bundle.js"
sourceMaps = false
devServerProperty =
KotlinWebpackConfig.DevServer(
open = false,
Expand Down
125 changes: 122 additions & 3 deletions webinterface/src/jsMain/kotlin/WatermarkTextEmbedTab.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import de.fraunhofer.isst.trend.watermarker.Watermarker
import de.fraunhofer.isst.trend.watermarker.fileWatermarker.TextWatermarker
import de.fraunhofer.isst.trend.watermarker.returnTypes.Result
import de.fraunhofer.isst.trend.watermarker.watermarks.TextWatermark
import de.fraunhofer.isst.trend.watermarker.watermarks.Watermark
import io.kvision.core.FontWeight
import io.kvision.core.Placement
import io.kvision.core.TooltipOptions
import io.kvision.core.Trigger
import io.kvision.core.enableTooltip
import io.kvision.core.onInput
import io.kvision.form.FormMethod
import io.kvision.form.check.CheckBox
import io.kvision.form.formPanel
import io.kvision.form.text.Text
import io.kvision.form.text.TextArea
Expand All @@ -24,10 +25,13 @@ import io.kvision.html.ButtonStyle
import io.kvision.html.button
import io.kvision.html.div
import io.kvision.html.span
import io.kvision.i18n.tr
import io.kvision.modal.Confirm
import io.kvision.modal.Modal
import io.kvision.panel.HPanel
import io.kvision.panel.SimplePanel
import io.kvision.panel.fieldsetPanel
import io.kvision.panel.hPanel
import io.kvision.progress.Progress
import io.kvision.progress.progressNumeric
import io.kvision.state.ObservableValue
Expand All @@ -43,6 +47,10 @@ import kotlin.math.round
data class WatermarkerTextForm(
val watermark: String,
val text: String,
val trendmarkCompressed: Boolean,
val trendmarkSized: Boolean,
val trendmarkCRC32: Boolean,
val trendmarkSHA3256: Boolean,
)

class WatermarkTextEmbedTab : SimplePanel() {
Expand Down Expand Up @@ -72,6 +80,62 @@ class WatermarkTextEmbedTab : SimplePanel() {
)
}

private val compressedCheckBox =
CheckBox(label = "Compressed &#9432;", rich = true) {
paddingRight = 20.px
enableTooltip(
TooltipOptions(
title =
"Compress the watermark content before embedding into" +
" the text. Good for longer watermarks.",
triggers = listOf(Trigger.HOVER),
),
)
}

private val sizedCheckBox =
CheckBox(label = "Sized &#9432;", rich = true) {
paddingRight = 20.px
enableTooltip(
TooltipOptions(
title =
"Include the size of the watermark for additional " +
"verification. Needs a longer cover text content.",
triggers = listOf(Trigger.HOVER),
),
)
}

@Suppress("ktlint:standard:property-naming")
private val CRC32CheckBox =
CheckBox(label = "CRC32 &#9432;", rich = true) {
paddingRight = 20.px
enableTooltip(
TooltipOptions(
title =
"Uses the Cyclic Redundancy Check (CRC) " +
"error-detecting code for additional robustness. " +
"Needs a longer cover text content.",
triggers = listOf(Trigger.HOVER),
),
)
}

@Suppress("ktlint:standard:property-naming")
private val SHA3256CheckBox =
CheckBox(label = "SHA3-256 &#9432;", rich = true) {
paddingRight = 20.px
enableTooltip(
TooltipOptions(
title =
"Include a SHA3-256 hash of the watermark for " +
"additional verification. Needs a longer cover text " +
"content.",
triggers = listOf(Trigger.HOVER),
),
)
}

// Progress bar
private var min: Int = -1
private val capacityObservable = ObservableValue(-1)
Expand Down Expand Up @@ -151,7 +215,30 @@ class WatermarkTextEmbedTab : SimplePanel() {
coverTextInput,
required = true,
)
fieldsetPanel(tr("Advanced Settings")) {
hPanel {
div("Trendmark: &#9432;", rich = true) {
paddingRight = 10.px
fontWeight = FontWeight.BOLD
enableTooltip(
TooltipOptions(
title =
"A special type of watermarks using additional " +
"features.",
triggers = listOf(Trigger.HOVER),
),
)
}

add(compressedCheckBox.bind(WatermarkerTextForm::trendmarkCompressed))

add(sizedCheckBox.bind(WatermarkerTextForm::trendmarkSized))

add(CRC32CheckBox.bind(WatermarkerTextForm::trendmarkCRC32))

add(SHA3256CheckBox.bind(WatermarkerTextForm::trendmarkSHA3256))
}
}
add(progressBar)
span().bind(capacityObservable) {
val percentage =
Expand All @@ -164,6 +251,10 @@ class WatermarkTextEmbedTab : SimplePanel() {
// Check if watermark fits into the cover text
watermarkerInput.onInput { updateCapacity() }
coverTextInput.onInput { updateCapacity() }
compressedCheckBox.onInput { updateCapacity() }
sizedCheckBox.onInput { updateCapacity() }
CRC32CheckBox.onInput { updateCapacity() }
SHA3256CheckBox.onInput { updateCapacity() }

textFormPanel.add(
HPanel {
Expand All @@ -178,6 +269,10 @@ class WatermarkTextEmbedTab : SimplePanel() {
addWatermarkToText(
textFormPanel.getData().watermark,
textFormPanel.getData().text,
textFormPanel.getData().trendmarkCompressed,
textFormPanel.getData().trendmarkSized,
textFormPanel.getData().trendmarkCRC32,
textFormPanel.getData().trendmarkSHA3256,
)

if (watermarkedResult.isSuccess) {
Expand Down Expand Up @@ -253,6 +348,10 @@ class WatermarkTextEmbedTab : SimplePanel() {
watermarkFitsInText(
watermarkerInput.value.toString(),
coverTextInput.value.toString(),
compressedCheckBox.value,
sizedCheckBox.value,
CRC32CheckBox.value,
SHA3256CheckBox.value,
)

// Enable or disable the submit form button and user hint
Expand All @@ -277,9 +376,19 @@ class WatermarkTextEmbedTab : SimplePanel() {
private fun addWatermarkToText(
watermarkString: String,
text: String,
trendmarkCompressed: Boolean = false,
trendmarkSized: Boolean = false,
trendmarkCRC32: Boolean = false,
trendmarkSHA3256: Boolean = false,
): Result<String> {
val watermarker = Watermarker()
val watermark = TextWatermark.new(watermarkString)
val watermark =
TextWatermark.raw(watermarkString).apply {
if (trendmarkCompressed) compressed()
if (trendmarkSized) sized()
if (trendmarkCRC32) CRC32()
if (trendmarkSHA3256) SHA3256()
}
return watermarker.textAddWatermark(text, watermark)
}

Expand All @@ -294,8 +403,18 @@ class WatermarkTextEmbedTab : SimplePanel() {
private fun watermarkFitsInText(
watermark: String,
text: String,
trendmarkCompressed: Boolean,
trendmarkSized: Boolean,
trendmarkCRC32: Boolean,
trendmarkSHA3256: Boolean,
): Int {
val parsedWatermark = Watermark.fromString(watermark)
val parsedWatermark =
TextWatermark.raw(watermark).apply {
if (trendmarkCompressed) compressed()
if (trendmarkSized) sized()
if (trendmarkCRC32) CRC32()
if (trendmarkSHA3256) SHA3256()
}

val numberOfInsertPositions = textWatermarker.placement(text).count()
val numberOfNeededPositions = textWatermarker.getMinimumInsertPositions(parsedWatermark)
Expand Down
10 changes: 5 additions & 5 deletions webinterface/src/jsMain/kotlin/WatermarkTextExtractTab.kt
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class WatermarkTextExtractTab : SimplePanel() {
if (watermarkedResult.value.isNullOrEmpty()) {
modal.add(
div(
"Could not find any valid watermark in the" +
"Could not find any valid watermark in the " +
"text.",
className = "alert alert-secondary",
),
Expand Down Expand Up @@ -167,22 +167,22 @@ class WatermarkTextExtractTab : SimplePanel() {
modal.add(watermarkDetailsPanel)
}
// Warning
} else if (watermarkedResult.status.isWarning) {
} else if (watermarkedResult.isWarning) {
modal.add(
div(
"Some problems occur during the extraction: " +
watermarkedResult.status.getMessage(),
watermarkedResult.getMessage(),
className = "alert alert-warning",
),
)
modal.add(strong("Extracted Data: "))
modal.add(p(getWatermarkStringList(watermarkedResult).toString()))
// Error
} else if (watermarkedResult.status.isError) {
} else if (watermarkedResult.isError) {
modal.add(
div(
"An error occurs during the extraction: " +
watermarkedResult.status.getMessage(),
watermarkedResult.getMessage(),
className = "alert alert-danger",
),
)
Expand Down
1 change: 0 additions & 1 deletion webinterface/webpack.config.d/webpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ config.resolve.conditionNames = ['import', 'require', 'default'];

if (config.devServer) {
config.devServer.hot = true;
config.devtool = 'eval-cheap-source-map';
} else {
config.devtool = undefined;
}
Expand Down

0 comments on commit 9e6fb05

Please sign in to comment.