diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini
index 4ab0c29..55a7e97 100644
--- a/data/locale/en-US.ini
+++ b/data/locale/en-US.ini
@@ -54,3 +54,11 @@ YouTubeServer="YouTube Server"
YouTubeServerInfo="Pick a YouTube live server. If you aren't sure which to pick, pick the first one."
YouTubeStreamKey="YouTube Stream Key"
YouTubeStreamKeyInfo="Please enter your stream key, you can find this on your YouTube Creator Dashboard."
+
+# TikTok Output Dialog
+TikTokOutput="TikTok Output"
+TikTokServiceInfo="Please complete the following fields to add a new TikTok output.
Note: If you do not have access to a stream key, you will not be able to use Aitum Multistream to send an output to Tiktok. We also cannot provide stream keys/access."
+TikTokServer="TikTok Server"
+TikTokServerInfo="Please enter your stream server, you can find this on your TikTok Live Center."
+TikTokStreamKey="TikTok Stream Key"
+TikTokStreamKeyInfo="Please enter your stream key, you can find this on your TikTok Live Center."
diff --git a/output-dialog.cpp b/output-dialog.cpp
index 71de509..6bf7e1a 100644
--- a/output-dialog.cpp
+++ b/output-dialog.cpp
@@ -510,14 +510,114 @@ QWidget *OutputDialog::WizardInfoTrovo() {
QWidget *OutputDialog::WizardInfoTikTok() {
auto page = new QWidget(this);
-
- auto pageLayout = new QVBoxLayout;
+ page->setStyleSheet("padding: 0px; margin: 0px;");
- auto title = new QLabel(QString("Tiktok Service page"));
+ // Layout
+ auto pageLayout = new QVBoxLayout;
+ pageLayout->setSpacing(12);
+
+ // Heading
+ auto title = new QLabel(QString::fromUtf8(obs_module_text("TikTokServiceInfo")));
+ title->setWordWrap(true);
+ title->setTextFormat(Qt::RichText);
pageLayout->addWidget(title);
+ // Content
+ auto contentLayout = new QVBoxLayout;
+
+ // Confirm button - initialised here so we can set state in form input connects
+ auto confirmButton = generateButton(QString("Create Output"));
+
+ // Form
+ auto formLayout = new QFormLayout;
+ formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
+ formLayout->setLabelAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
+ formLayout->setSpacing(12);
+
+ // Output name
+ auto outputNameField = new QLineEdit;
+ outputNameField->setText(QString::fromUtf8(obs_module_text("TikTokOutput")));
+ outputNameField->setStyleSheet("padding: 4px 8px;");
+
+ connect(outputNameField, &QLineEdit::textEdited, [this, outputNameField, confirmButton] {
+ outputName = outputNameField->text();
+ validateOutputs(confirmButton);
+ });
+
+ formLayout->addRow(generateFormLabel("OutputName"), outputNameField);
+
+ // Server field
+ auto serverSelection = new QLineEdit;
+ serverSelection->setStyleSheet("padding: 4px 8px;");
+
+ connect(serverSelection, &QLineEdit::textEdited, [this, serverSelection, confirmButton] {
+ outputServer = serverSelection->text();
+ validateOutputs(confirmButton);
+ });
+
+ formLayout->addRow(generateFormLabel("TikTokServer"), serverSelection);
+
+ // Server info
+ formLayout->addWidget(generateInfoLabel("TikTokServerInfo"));
+
+ // Server key
+ auto outputKeyField = new QLineEdit;
+ outputKeyField->setStyleSheet("padding: 4px 8px;");
+ connect(outputKeyField, &QLineEdit::textEdited, [this, outputKeyField, confirmButton] {
+ outputKey = outputKeyField->text();
+ validateOutputs(confirmButton);
+ });
+
+ formLayout->addRow(generateFormLabel("TikTokStreamKey"), outputKeyField);
+
+ // Server key info
+ formLayout->addWidget(generateInfoLabel("TikTokStreamKeyInfo"));
+
+ contentLayout->addLayout(formLayout);
+
+ // spacing
+ auto spacer = new QSpacerItem(1, 20, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
+ contentLayout->addSpacerItem(spacer);
+
+ pageLayout->addLayout(contentLayout);
+
+ // Controls
+ auto controlsLayout = new QHBoxLayout;
+ controlsLayout->setSpacing(12);
+
+ // back button
+ auto serviceButton = generateButton(QString("< Back"));
+
+ connect(serviceButton, &QPushButton::clicked, [this] {
+ stackedWidget->setCurrentIndex(0);
+ resetOutputs();
+ });
+
+ controlsLayout->addWidget(serviceButton, 0);
+ controlsLayout->addStretch(1);
+
+ // confirm button (initialised above so we can set state)
+ connect(confirmButton, &QPushButton::clicked, [this] {
+ acceptOutputs();
+ });
+
+ controlsLayout->addWidget(confirmButton, 0);
+
+ // Hook it all together
+ pageLayout->addLayout(controlsLayout);
page->setLayout(pageLayout);
+ // Defaults for when we're changed to
+ connect(stackedWidget, &QStackedWidget::currentChanged, [this, outputNameField, serverSelection, outputKeyField, confirmButton] {
+ if (stackedWidget->currentIndex() == 7) {
+ outputName = outputNameField->text();
+ outputServer = serverSelection->text();
+ outputKey = outputKeyField->text();
+ validateOutputs(confirmButton);
+ }
+ });
+
+
return page;
}