Merge "Add id of inactive account to AccountException"
diff --git a/java/com/google/gerrit/pgm/Daemon.java b/java/com/google/gerrit/pgm/Daemon.java
index b3e4dfc..316fee9 100644
--- a/java/com/google/gerrit/pgm/Daemon.java
+++ b/java/com/google/gerrit/pgm/Daemon.java
@@ -92,6 +92,7 @@
import com.google.gerrit.server.config.GerritRuntime;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.LogConfig;
+import com.google.gerrit.server.config.SendEmailEnabledModule;
import com.google.gerrit.server.config.SysExecutorModule;
import com.google.gerrit.server.events.EventBroker.EventBrokerModule;
import com.google.gerrit.server.events.StreamEventsApiListener.StreamEventsApiListenerModule;
@@ -543,6 +544,7 @@
modules.add(new StartupChecksModule());
modules.add(new GerritInstanceNameModule());
modules.add(new GerritInstanceIdModule());
+ modules.add(new SendEmailEnabledModule());
if (MoreObjects.firstNonNull(httpd, true)) {
modules.add(
new CanonicalWebUrlModule() {
diff --git a/java/com/google/gerrit/server/change/ChangeInserter.java b/java/com/google/gerrit/server/change/ChangeInserter.java
index 3f7b2bb..fad9208 100644
--- a/java/com/google/gerrit/server/change/ChangeInserter.java
+++ b/java/com/google/gerrit/server/change/ChangeInserter.java
@@ -58,6 +58,7 @@
import com.google.gerrit.server.change.ReviewerModifier.InternalReviewerInput;
import com.google.gerrit.server.change.ReviewerModifier.ReviewerModification;
import com.google.gerrit.server.change.ReviewerModifier.ReviewerModificationList;
+import com.google.gerrit.server.config.SendEmailEnabled;
import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.events.CommitReceivedEvent;
import com.google.gerrit.server.extensions.events.CommentAdded;
@@ -136,6 +137,7 @@
private final DiffOperationsForCommitValidation.Factory diffOperationsForCommitValidationFactory;
private final PluginSetContext<ValidationOptionsListener> validationOptionsListeners;
private final PluginSetContext<CommitValidationInfoListener> commitValidationInfoListeners;
+ private final boolean sendEmailEnabled;
private final Change.Id changeId;
private final PatchSet.Id psId;
@@ -184,6 +186,7 @@
ChangeMessagesUtil cmUtil,
EmailFactories emailFactories,
@SendEmailExecutor ExecutorService sendEmailExecutor,
+ @SendEmailEnabled Boolean sendEmailEnabled,
CommitValidators.Factory commitValidatorsFactory,
TopicValidator topicValidator,
CommentAdded commentAdded,
@@ -226,6 +229,7 @@
this.approvals = Collections.emptyMap();
this.fireRevisionCreated = true;
this.sendMail = true;
+ this.sendEmailEnabled = sendEmailEnabled;
this.updateRef = true;
}
@@ -601,7 +605,7 @@
public void postUpdate(PostUpdateContext ctx) throws Exception {
reviewerAdditions.postUpdate(ctx);
NotifyResolver.Result notify = ctx.getNotify(change.getId());
- if (sendMail) {
+ if (sendMail && sendEmailEnabled) {
Runnable sender =
new Runnable() {
@Override
diff --git a/java/com/google/gerrit/server/change/EmailNewPatchSet.java b/java/com/google/gerrit/server/change/EmailNewPatchSet.java
index 30d82a4..dc6935e 100644
--- a/java/com/google/gerrit/server/change/EmailNewPatchSet.java
+++ b/java/com/google/gerrit/server/change/EmailNewPatchSet.java
@@ -16,6 +16,8 @@
import static com.google.gerrit.server.mail.EmailFactories.NEW_PATCHSET_ADDED;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
@@ -29,6 +31,7 @@
import com.google.gerrit.extensions.client.ChangeKind;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.config.SendEmailEnabled;
import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.mail.EmailFactories;
import com.google.gerrit.server.mail.send.ChangeEmail;
@@ -68,13 +71,15 @@
private final ExecutorService sendEmailExecutor;
private final ThreadLocalRequestContext threadLocalRequestContext;
- private final AsyncSender asyncSender;
+ private final Supplier<AsyncSender> asyncSenderSupplier;
+ private final boolean sendEmailEnabled;
private RequestScopePropagator requestScopePropagator;
@Inject
EmailNewPatchSet(
@SendEmailExecutor ExecutorService sendEmailExecutor,
+ @SendEmailEnabled Boolean sendEmailEnabled,
ThreadLocalRequestContext threadLocalRequestContext,
EmailFactories emailFactories,
PatchSetInfoFactory patchSetInfoFactory,
@@ -88,45 +93,49 @@
@Assisted ChangeKind changeKind,
@Assisted ObjectId preUpdateMetaId) {
this.sendEmailExecutor = sendEmailExecutor;
+ this.sendEmailEnabled = sendEmailEnabled;
this.threadLocalRequestContext = threadLocalRequestContext;
- MessageId messageId;
- try {
- messageId =
- messageIdGenerator.fromChangeUpdateAndReason(
- postUpdateContext.getRepoView(), patchSet.id(), "EmailReplacePatchSet");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
+ this.asyncSenderSupplier =
+ Suppliers.memoize(
+ () -> {
+ MessageId messageId;
+ try {
+ messageId =
+ messageIdGenerator.fromChangeUpdateAndReason(
+ postUpdateContext.getRepoView(), patchSet.id(), "EmailReplacePatchSet");
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
- Change.Id changeId = patchSet.id().changeId();
+ Change.Id changeId = patchSet.id().changeId();
- // Getting the change data from PostUpdateContext retrieves a cached ChangeData
- // instance. This ChangeData instance has been created when the change was (re)indexed
- // due to the update, and hence has submit requirement results already cached (since
- // (re)indexing triggers the evaluation of the submit requirements).
- Map<SubmitRequirement, SubmitRequirementResult> postUpdateSubmitRequirementResults =
- postUpdateContext
- .getChangeData(postUpdateContext.getProject(), changeId)
- .submitRequirementsIncludingLegacy();
- this.asyncSender =
- new AsyncSender(
- postUpdateContext.getIdentifiedUser(),
- emailFactories,
- patchSetInfoFactory,
- messageId,
- postUpdateContext.getNotify(changeId),
- postUpdateContext.getProject(),
- changeId,
- patchSet,
- message,
- postUpdateContext.getWhen(),
- outdatedApprovals,
- reviewers,
- extraCcs,
- changeKind,
- preUpdateMetaId,
- postUpdateSubmitRequirementResults);
+ // Getting the change data from PostUpdateContext retrieves a cached ChangeData
+ // instance. This ChangeData instance has been created when the change was (re)indexed
+ // due to the update, and hence has submit requirement results already cached (since
+ // (re)indexing triggers the evaluation of the submit requirements).
+ Map<SubmitRequirement, SubmitRequirementResult> postUpdateSubmitRequirementResults =
+ postUpdateContext
+ .getChangeData(postUpdateContext.getProject(), changeId)
+ .submitRequirementsIncludingLegacy();
+ return new AsyncSender(
+ postUpdateContext.getIdentifiedUser(),
+ emailFactories,
+ patchSetInfoFactory,
+ messageId,
+ postUpdateContext.getNotify(changeId),
+ postUpdateContext.getProject(),
+ changeId,
+ patchSet,
+ message,
+ postUpdateContext.getWhen(),
+ outdatedApprovals,
+ reviewers,
+ extraCcs,
+ changeKind,
+ preUpdateMetaId,
+ postUpdateSubmitRequirementResults);
+ });
}
public EmailNewPatchSet setRequestScopePropagator(RequestScopePropagator requestScopePropagator) {
@@ -135,15 +144,19 @@
}
public void sendAsync() {
+ if (!sendEmailEnabled) {
+ return;
+ }
@SuppressWarnings("unused")
Future<?> possiblyIgnoredError =
sendEmailExecutor.submit(
requestScopePropagator != null
- ? requestScopePropagator.wrap(asyncSender)
+ ? requestScopePropagator.wrap(asyncSenderSupplier.get())
: () -> {
- RequestContext old = threadLocalRequestContext.setContext(asyncSender);
+ RequestContext old =
+ threadLocalRequestContext.setContext(asyncSenderSupplier.get());
try {
- asyncSender.run();
+ asyncSenderSupplier.get().run();
} finally {
@SuppressWarnings("unused")
var unused = threadLocalRequestContext.setContext(old);
diff --git a/java/com/google/gerrit/server/change/EmailReviewComments.java b/java/com/google/gerrit/server/change/EmailReviewComments.java
index bb93cd3..880cca3 100644
--- a/java/com/google/gerrit/server/change/EmailReviewComments.java
+++ b/java/com/google/gerrit/server/change/EmailReviewComments.java
@@ -17,6 +17,8 @@
import static com.google.gerrit.server.CommentsUtil.COMMENT_ORDER;
import static com.google.gerrit.server.mail.EmailFactories.COMMENTS_ADDED;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
@@ -28,6 +30,7 @@
import com.google.gerrit.entities.SubmitRequirementResult;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.config.SendEmailEnabled;
import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.mail.EmailFactories;
import com.google.gerrit.server.mail.send.ChangeEmail;
@@ -82,11 +85,13 @@
}
private final ExecutorService sendEmailsExecutor;
- private final AsyncSender asyncSender;
+ private final Supplier<AsyncSender> asyncSenderSupplier;
+ private final boolean sendEmailEnabled;
@Inject
EmailReviewComments(
@SendEmailExecutor ExecutorService executor,
+ @SendEmailEnabled Boolean sendEmailEnabled,
PatchSetInfoFactory patchSetInfoFactory,
EmailFactories emailFactories,
ThreadLocalRequestContext requestContext,
@@ -99,49 +104,56 @@
@Nullable @Assisted("patchSetComment") String patchSetComment,
@Assisted List<LabelVote> labels) {
this.sendEmailsExecutor = executor;
+ this.sendEmailEnabled = sendEmailEnabled;
- MessageId messageId;
- try {
- messageId =
- messageIdGenerator.fromChangeUpdateAndReason(
- postUpdateContext.getRepoView(), patchSet.id(), "EmailReviewComments");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
+ this.asyncSenderSupplier =
+ Suppliers.memoize(
+ () -> {
+ MessageId messageId;
+ try {
+ messageId =
+ messageIdGenerator.fromChangeUpdateAndReason(
+ postUpdateContext.getRepoView(), patchSet.id(), "EmailReviewComments");
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
- Change.Id changeId = patchSet.id().changeId();
+ Change.Id changeId = patchSet.id().changeId();
- // Getting the change data from PostUpdateContext retrieves a cached ChangeData
- // instance. This ChangeData instance has been created when the change was (re)indexed
- // due to the update, and hence has submit requirement results already cached (since
- // (re)indexing triggers the evaluation of the submit requirements).
- Map<SubmitRequirement, SubmitRequirementResult> postUpdateSubmitRequirementResults =
- postUpdateContext
- .getChangeData(postUpdateContext.getProject(), changeId)
- .submitRequirementsIncludingLegacy();
- this.asyncSender =
- new AsyncSender(
- requestContext,
- emailFactories,
- patchSetInfoFactory,
- postUpdateContext.getUser().asIdentifiedUser(),
- messageId,
- postUpdateContext.getNotify(changeId),
- postUpdateContext.getProject(),
- changeId,
- patchSet,
- preUpdateMetaId,
- message,
- postUpdateContext.getWhen(),
- ImmutableList.copyOf(COMMENT_ORDER.sortedCopy(comments)),
- patchSetComment,
- ImmutableList.copyOf(labels),
- postUpdateSubmitRequirementResults);
+ // Getting the change data from PostUpdateContext retrieves a cached ChangeData
+ // instance. This ChangeData instance has been created when the change was (re)indexed
+ // due to the update, and hence has submit requirement results already cached (since
+ // (re)indexing triggers the evaluation of the submit requirements).
+ Map<SubmitRequirement, SubmitRequirementResult> postUpdateSubmitRequirementResults =
+ postUpdateContext
+ .getChangeData(postUpdateContext.getProject(), changeId)
+ .submitRequirementsIncludingLegacy();
+ return new AsyncSender(
+ requestContext,
+ emailFactories,
+ patchSetInfoFactory,
+ postUpdateContext.getUser().asIdentifiedUser(),
+ messageId,
+ postUpdateContext.getNotify(changeId),
+ postUpdateContext.getProject(),
+ changeId,
+ patchSet,
+ preUpdateMetaId,
+ message,
+ postUpdateContext.getWhen(),
+ ImmutableList.copyOf(COMMENT_ORDER.sortedCopy(comments)),
+ patchSetComment,
+ ImmutableList.copyOf(labels),
+ postUpdateSubmitRequirementResults);
+ });
}
public void sendAsync() {
+ if (!sendEmailEnabled) {
+ return;
+ }
@SuppressWarnings("unused")
- Future<?> possiblyIgnoredError = sendEmailsExecutor.submit(asyncSender);
+ Future<?> possiblyIgnoredError = sendEmailsExecutor.submit(asyncSenderSupplier.get());
}
/**
diff --git a/java/com/google/gerrit/server/change/ModifyReviewersEmail.java b/java/com/google/gerrit/server/change/ModifyReviewersEmail.java
index cac40d1..369d080 100644
--- a/java/com/google/gerrit/server/change/ModifyReviewersEmail.java
+++ b/java/com/google/gerrit/server/change/ModifyReviewersEmail.java
@@ -23,6 +23,7 @@
import com.google.gerrit.entities.Address;
import com.google.gerrit.entities.Change;
import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.config.SendEmailEnabled;
import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.mail.EmailFactories;
import com.google.gerrit.server.mail.send.ChangeEmail;
@@ -42,14 +43,17 @@
private final EmailFactories emailFactories;
private final ExecutorService sendEmailsExecutor;
private final MessageIdGenerator messageIdGenerator;
+ private final boolean sendEmailEnabled;
@Inject
ModifyReviewersEmail(
EmailFactories emailFactories,
@SendEmailExecutor ExecutorService sendEmailsExecutor,
+ @SendEmailEnabled Boolean sendEmailEnabled,
MessageIdGenerator messageIdGenerator) {
this.emailFactories = emailFactories;
this.sendEmailsExecutor = sendEmailsExecutor;
+ this.sendEmailEnabled = sendEmailEnabled;
this.messageIdGenerator = messageIdGenerator;
}
@@ -63,6 +67,9 @@
Collection<Address> copiedByEmail,
Collection<Address> removedByEmail,
NotifyResolver.Result notify) {
+ if (!sendEmailEnabled) {
+ return;
+ }
// The user knows they added/removed themselves, don't bother emailing them.
Account.Id userId = user.getAccountId();
ImmutableList<Account.Id> immutableToMail =
diff --git a/java/com/google/gerrit/server/config/SendEmailEnabled.java b/java/com/google/gerrit/server/config/SendEmailEnabled.java
new file mode 100644
index 0000000..f52349f
--- /dev/null
+++ b/java/com/google/gerrit/server/config/SendEmailEnabled.java
@@ -0,0 +1,25 @@
+// Copyright (C) 2026 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.config;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+import java.lang.annotation.Retention;
+
+/** Marker on a {@link Boolean} holding whether email sending is enabled. */
+@Retention(RUNTIME)
+@BindingAnnotation
+public @interface SendEmailEnabled {}
diff --git a/java/com/google/gerrit/server/config/SendEmailEnabledModule.java b/java/com/google/gerrit/server/config/SendEmailEnabledModule.java
new file mode 100644
index 0000000..9f4e071
--- /dev/null
+++ b/java/com/google/gerrit/server/config/SendEmailEnabledModule.java
@@ -0,0 +1,30 @@
+// Copyright (C) 2026 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.config;
+
+import static com.google.inject.Scopes.SINGLETON;
+
+import com.google.inject.AbstractModule;
+
+/** Supports binding the {@link SendEmailEnabled} annotation. */
+public class SendEmailEnabledModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ bind(Boolean.class)
+ .annotatedWith(SendEmailEnabled.class)
+ .toProvider(SendEmailEnabledProvider.class)
+ .in(SINGLETON);
+ }
+}
diff --git a/java/com/google/gerrit/server/config/SendEmailEnabledProvider.java b/java/com/google/gerrit/server/config/SendEmailEnabledProvider.java
new file mode 100644
index 0000000..a9a5a39
--- /dev/null
+++ b/java/com/google/gerrit/server/config/SendEmailEnabledProvider.java
@@ -0,0 +1,36 @@
+// Copyright (C) 2026 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.config;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import org.eclipse.jgit.lib.Config;
+
+/** Provides whether email sending is enabled from {@code sendemail.enable}. */
+@Singleton
+public class SendEmailEnabledProvider implements Provider<Boolean> {
+ private final boolean enabled;
+
+ @Inject
+ public SendEmailEnabledProvider(@GerritServerConfig Config cfg) {
+ enabled = cfg.getBoolean("sendemail", null, "enable", true);
+ }
+
+ @Override
+ public Boolean get() {
+ return enabled;
+ }
+}
diff --git a/java/com/google/gerrit/server/git/MergedByPushOp.java b/java/com/google/gerrit/server/git/MergedByPushOp.java
index a3c8deb..3360c3f 100644
--- a/java/com/google/gerrit/server/git/MergedByPushOp.java
+++ b/java/com/google/gerrit/server/git/MergedByPushOp.java
@@ -25,6 +25,7 @@
import com.google.gerrit.entities.SubmissionId;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.PatchSetUtil;
+import com.google.gerrit.server.config.SendEmailEnabled;
import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.extensions.events.ChangeMerged;
import com.google.gerrit.server.mail.EmailFactories;
@@ -76,6 +77,7 @@
private final ExecutorService sendEmailExecutor;
private final ChangeMerged changeMerged;
private final MessageIdGenerator messageIdGenerator;
+ private final boolean sendEmailEnabled;
private final PatchSet.Id psId;
private final SubmissionId submissionId;
@@ -95,6 +97,7 @@
EmailFactories emailFactories,
PatchSetUtil psUtil,
@SendEmailExecutor ExecutorService sendEmailExecutor,
+ @SendEmailEnabled Boolean sendEmailEnabled,
ChangeMerged changeMerged,
MessageIdGenerator messageIdGenerator,
@Assisted RequestScopePropagator requestScopePropagator,
@@ -107,6 +110,7 @@
this.emailFactories = emailFactories;
this.psUtil = psUtil;
this.sendEmailExecutor = sendEmailExecutor;
+ this.sendEmailEnabled = sendEmailEnabled;
this.changeMerged = changeMerged;
this.messageIdGenerator = messageIdGenerator;
this.requestScopePropagator = requestScopePropagator;
@@ -182,41 +186,44 @@
if (!correctBranch) {
return;
}
- @SuppressWarnings("unused") // Runnable already handles errors
- Future<?> possiblyIgnoredError =
- sendEmailExecutor.submit(
- requestScopePropagator.wrap(
- new Runnable() {
- @Override
- public void run() {
- try {
- // The stickyApprovalDiff is always empty here since this is not supported
- // for direct pushes.
- ChangeEmail changeEmail =
- emailFactories.createChangeEmail(
- ctx.getProject(),
- psId.changeId(),
- emailFactories.createMergedChangeEmail(
- /* stickyApprovalDiff= */ Optional.empty(),
- /* modifiedFiles= */ List.of()));
- changeEmail.setPatchSet(patchSet, info);
- OutgoingEmail outgoingEmail =
- emailFactories.createOutgoingEmail(CHANGE_MERGED, changeEmail);
- outgoingEmail.setFrom(ctx.getAccountId());
- outgoingEmail.setMessageId(
- messageIdGenerator.fromChangeUpdate(ctx.getRepoView(), patchSet.id()));
- outgoingEmail.send();
- } catch (Exception e) {
- logger.atSevere().withCause(e).log(
- "Cannot send email for submitted patch set %s", psId);
- }
- }
- @Override
- public String toString() {
- return "send-email merged";
- }
- }));
+ if (sendEmailEnabled) {
+ @SuppressWarnings("unused") // Runnable already handles errors
+ Future<?> possiblyIgnoredError =
+ sendEmailExecutor.submit(
+ requestScopePropagator.wrap(
+ new Runnable() {
+ @Override
+ public void run() {
+ try {
+ // The stickyApprovalDiff is always empty here since this is not supported
+ // for direct pushes.
+ ChangeEmail changeEmail =
+ emailFactories.createChangeEmail(
+ ctx.getProject(),
+ psId.changeId(),
+ emailFactories.createMergedChangeEmail(
+ /* stickyApprovalDiff= */ Optional.empty(),
+ /* modifiedFiles= */ List.of()));
+ changeEmail.setPatchSet(patchSet, info);
+ OutgoingEmail outgoingEmail =
+ emailFactories.createOutgoingEmail(CHANGE_MERGED, changeEmail);
+ outgoingEmail.setFrom(ctx.getAccountId());
+ outgoingEmail.setMessageId(
+ messageIdGenerator.fromChangeUpdate(ctx.getRepoView(), patchSet.id()));
+ outgoingEmail.send();
+ } catch (Exception e) {
+ logger.atSevere().withCause(e).log(
+ "Cannot send email for submitted patch set %s", psId);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "send-email merged";
+ }
+ }));
+ }
changeMerged.fire(
ctx.getChangeData(change), patchSet, ctx.getAccount(), mergeResultRevId, ctx.getWhen());
diff --git a/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java b/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
index 7e5855d..c050c13 100644
--- a/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
+++ b/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
@@ -27,6 +27,7 @@
import com.google.gerrit.exceptions.EmailException;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.config.SendEmailEnabled;
import com.google.gerrit.server.mail.Encryption;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.AbstractModule;
@@ -91,8 +92,8 @@
private int expiryDays;
@Inject
- SmtpEmailSender(@GerritServerConfig Config cfg) {
- enabled = cfg.getBoolean("sendemail", null, "enable", true);
+ SmtpEmailSender(@GerritServerConfig Config cfg, @SendEmailEnabled Boolean enabled) {
+ this.enabled = enabled;
connectTimeout =
Ints.checkedCast(
ConfigUtil.getTimeUnit(
diff --git a/java/com/google/gerrit/server/submit/EmailMerge.java b/java/com/google/gerrit/server/submit/EmailMerge.java
index 4bd6f3d..25c7566 100644
--- a/java/com/google/gerrit/server/submit/EmailMerge.java
+++ b/java/com/google/gerrit/server/submit/EmailMerge.java
@@ -24,6 +24,7 @@
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.change.NotifyResolver;
+import com.google.gerrit.server.config.SendEmailEnabled;
import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.mail.EmailFactories;
import com.google.gerrit.server.mail.send.ChangeEmail;
@@ -59,6 +60,7 @@
private final EmailFactories emailFactories;
private final ThreadLocalRequestContext requestContext;
private final MessageIdGenerator messageIdGenerator;
+ private final boolean sendEmailEnabled;
private final Project.NameKey project;
private final Change change;
@@ -71,6 +73,7 @@
@Inject
EmailMerge(
@SendEmailExecutor ExecutorService executor,
+ @SendEmailEnabled Boolean sendEmailEnabled,
EmailFactories emailFactories,
ThreadLocalRequestContext requestContext,
MessageIdGenerator messageIdGenerator,
@@ -82,6 +85,7 @@
@Assisted String stickyApprovalDiff,
@Assisted List<FileDiffOutput> modifiedFiles) {
this.sendEmailsExecutor = executor;
+ this.sendEmailEnabled = sendEmailEnabled;
this.emailFactories = emailFactories;
this.requestContext = requestContext;
this.messageIdGenerator = messageIdGenerator;
@@ -95,6 +99,9 @@
}
void sendAsync() {
+ if (!sendEmailEnabled) {
+ return;
+ }
@SuppressWarnings("unused")
Future<?> possiblyIgnoredError = sendEmailsExecutor.submit(this);
}
diff --git a/java/com/google/gerrit/server/util/AttentionSetEmail.java b/java/com/google/gerrit/server/util/AttentionSetEmail.java
index 95fc246..e6a5f3d 100644
--- a/java/com/google/gerrit/server/util/AttentionSetEmail.java
+++ b/java/com/google/gerrit/server/util/AttentionSetEmail.java
@@ -17,12 +17,15 @@
import static com.google.gerrit.server.mail.EmailFactories.ATTENTION_SET_ADDED;
import static com.google.gerrit.server.mail.EmailFactories.ATTENTION_SET_REMOVED;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.change.NotifyResolver;
+import com.google.gerrit.server.config.SendEmailEnabled;
import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.mail.EmailFactories;
import com.google.gerrit.server.mail.send.AttentionSetChangeEmailDecorator;
@@ -63,11 +66,13 @@
}
private final ExecutorService sendEmailsExecutor;
- private final AsyncSender asyncSender;
+ private final Supplier<AsyncSender> asyncSenderSupplier;
+ private final boolean sendEmailEnabled;
@Inject
AttentionSetEmail(
@SendEmailExecutor ExecutorService executor,
+ @SendEmailEnabled Boolean sendEmailEnabled,
ThreadLocalRequestContext requestContext,
MessageIdGenerator messageIdGenerator,
AccountTemplateUtil accountTemplateUtil,
@@ -78,33 +83,40 @@
@Assisted String reason,
@Assisted Account.Id attentionUserId) {
this.sendEmailsExecutor = executor;
+ this.sendEmailEnabled = sendEmailEnabled;
- MessageId messageId;
- try {
- messageId =
- messageIdGenerator.fromChangeUpdateAndReason(
- ctx.getRepoView(), change.currentPatchSetId(), "AttentionSetEmail");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
+ this.asyncSenderSupplier =
+ Suppliers.memoize(
+ () -> {
+ MessageId messageId;
+ try {
+ messageId =
+ messageIdGenerator.fromChangeUpdateAndReason(
+ ctx.getRepoView(), change.currentPatchSetId(), "AttentionSetEmail");
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
- this.asyncSender =
- new AsyncSender(
- requestContext,
- emailFactories,
- ctx.getUser(),
- ctx.getProject(),
- attentionSetChange,
- messageId,
- ctx.getNotify(change.getId()),
- attentionUserId,
- accountTemplateUtil.replaceTemplates(reason),
- change.getId());
+ return new AsyncSender(
+ requestContext,
+ emailFactories,
+ ctx.getUser(),
+ ctx.getProject(),
+ attentionSetChange,
+ messageId,
+ ctx.getNotify(change.getId()),
+ attentionUserId,
+ accountTemplateUtil.replaceTemplates(reason),
+ change.getId());
+ });
}
public void sendAsync() {
+ if (!sendEmailEnabled) {
+ return;
+ }
@SuppressWarnings("unused")
- Future<?> possiblyIgnoredError = sendEmailsExecutor.submit(asyncSender);
+ Future<?> possiblyIgnoredError = sendEmailsExecutor.submit(asyncSenderSupplier.get());
}
/**
diff --git a/java/com/google/gerrit/testing/InMemoryModule.java b/java/com/google/gerrit/testing/InMemoryModule.java
index 657e1f2..745f89a 100644
--- a/java/com/google/gerrit/testing/InMemoryModule.java
+++ b/java/com/google/gerrit/testing/InMemoryModule.java
@@ -87,6 +87,7 @@
import com.google.gerrit.server.config.GerritServerId;
import com.google.gerrit.server.config.GerritServerIdProvider;
import com.google.gerrit.server.config.GlobalPluginConfigProvider;
+import com.google.gerrit.server.config.SendEmailEnabledModule;
import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.config.SitePath;
import com.google.gerrit.server.config.TrackingFooters;
@@ -267,6 +268,7 @@
install(NoSshKeyCache.module());
install(new GerritInstanceNameModule());
install(new GerritInstanceIdModule());
+ install(new SendEmailEnabledModule());
install(
new CanonicalWebUrlModule() {
@Override
diff --git a/polygerrit-ui/app/elements/chat-panel/chat-header.ts b/polygerrit-ui/app/elements/chat-panel/chat-header.ts
index 14e9894..3d465c4 100644
--- a/polygerrit-ui/app/elements/chat-panel/chat-header.ts
+++ b/polygerrit-ui/app/elements/chat-panel/chat-header.ts
@@ -121,6 +121,9 @@
md-icon-button md-icon {
color: var(--primary-text-color);
}
+ md-menu {
+ --md-menu-container-color: var(--dialog-background-color);
+ }
`;
@state() availableModels: ModelInfo[] = [];
diff --git a/polygerrit-ui/app/elements/chat-panel/context-chip.ts b/polygerrit-ui/app/elements/chat-panel/context-chip.ts
index 4b67ba5..ac95b4b 100644
--- a/polygerrit-ui/app/elements/chat-panel/context-chip.ts
+++ b/polygerrit-ui/app/elements/chat-panel/context-chip.ts
@@ -11,6 +11,7 @@
import {customElement, property, state} from 'lit/decorators.js';
import {when} from 'lit/directives/when.js';
+import {truncatePath} from '../../utils/path-list-util';
import {ContextItem} from '../../api/ai-code-review';
import {chatModelToken} from '../../models/chat/chat-model';
import {resolve} from '../../models/dependency';
@@ -74,6 +75,9 @@
--md-filter-chip-label-text-weight: var(--font-weight-medium);
--md-filter-chip-unselected-container-color: transparent;
--md-filter-chip-outline-color: var(--border-color);
+ --md-filter-chip-hover-label-text-color: var(--primary-text-color);
+ --md-filter-chip-focus-label-text-color: var(--primary-text-color);
+ --md-filter-chip-pressed-label-text-color: var(--primary-text-color);
overflow: hidden;
margin: 0;
border-radius: 8px;
@@ -112,8 +116,10 @@
'custom-action-chip': this.isCustomAction,
hidden: !this.supportsThisChange,
})}
- .label=${this.contextItem?.title ?? this.text}
- .title=${this.contextItem?.tooltip ?? this.tooltip ?? ''}
+ .title=${this.contextItem?.tooltip ??
+ this.tooltip ??
+ this.contextItem?.title ??
+ this.text}
@click=${this.navigateToUrl}
?removable=${this.isRemovable && !this.isSuggestion}
@remove=${this.onRemoveContextChip}
@@ -123,6 +129,7 @@
class=${this.isCustomAction ? 'custom-action-icon' : ''}
.icon=${icon}
></gr-icon>
+ ${truncatePath(this.contextItem?.title ?? this.text, 2)}
${when(
this.subText,
() => html`<span class="subtext">: ${this.subText}</span>`
diff --git a/polygerrit-ui/app/elements/chat-panel/context-chip_test.ts b/polygerrit-ui/app/elements/chat-panel/context-chip_test.ts
index fde442a..b9f0a65 100644
--- a/polygerrit-ui/app/elements/chat-panel/context-chip_test.ts
+++ b/polygerrit-ui/app/elements/chat-panel/context-chip_test.ts
@@ -14,6 +14,7 @@
import {chatProvider, createChange} from '../../test/test-data-generators';
import {changeModelToken} from '../../models/change/change-model';
import {ParsedChangeInfo} from '../../types/types';
+import {MdFilterChip} from '@material/web/chips/filter-chip';
suite('context-chip tests', () => {
let element: ContextChip;
@@ -48,7 +49,7 @@
element.text = 'test text';
await element.updateComplete;
const chip = element.shadowRoot?.querySelector('md-filter-chip');
- assert.equal(chip?.label, 'test text');
+ assert.equal(chip?.textContent?.trim(), 'test text');
});
test('renders with subtext', async () => {
@@ -128,4 +129,31 @@
chip?.click();
assert.isTrue(openSpy.calledWith('http://gerrit.test/test.ts', '_blank'));
});
+
+ test('shortens long context item titles', async () => {
+ const contextItem: ContextItem = {
+ type_id: 'file',
+ title: 'very/long/path/to/some/deeply/nested/file.ts',
+ link: '...',
+ };
+ element.contextItem = contextItem;
+ await element.updateComplete;
+ const chip =
+ element.shadowRoot?.querySelector<MdFilterChip>('md-filter-chip');
+ assert.equal(chip?.textContent?.trim(), '\u2026/nested/file.ts');
+ assert.equal(chip?.title, 'very/long/path/to/some/deeply/nested/file.ts');
+ });
+
+ test('does not shorten short context item titles', async () => {
+ const contextItem: ContextItem = {
+ type_id: 'file',
+ title: 'short/file.ts',
+ link: '...',
+ };
+ element.contextItem = contextItem;
+ await element.updateComplete;
+ const chip =
+ element.shadowRoot?.querySelector<MdFilterChip>('md-filter-chip');
+ assert.equal(chip?.textContent?.trim(), 'short/file.ts');
+ });
});
diff --git a/polygerrit-ui/app/elements/chat-panel/context-input-chip.ts b/polygerrit-ui/app/elements/chat-panel/context-input-chip.ts
index 7235b2e..22ce11f 100644
--- a/polygerrit-ui/app/elements/chat-panel/context-input-chip.ts
+++ b/polygerrit-ui/app/elements/chat-panel/context-input-chip.ts
@@ -69,6 +69,12 @@
--md-assist-chip-label-text-weight: var(--font-weight-medium);
--md-assist-chip-label-text-color: var(--primary-text-color);
--md-assist-chip-outline-color: var(--border-color);
+ --md-assist-chip-hover-label-text-color: var(--primary-text-color);
+ --md-assist-chip-focus-label-text-color: var(--primary-text-color);
+ --md-assist-chip-pressed-label-text-color: var(--primary-text-color);
+ --md-assist-chip-hover-icon-color: var(--primary-text-color);
+ --md-assist-chip-focus-icon-color: var(--primary-text-color);
+ --md-assist-chip-pressed-icon-color: var(--primary-text-color);
overflow: hidden;
margin: 0;
border-color: var(--border-color);
@@ -99,6 +105,8 @@
background-color: var(--background-color-primary);
font-family: var(--font-family);
font-size: var(--font-size-normal);
+ /* input color often defaults to browser/os default which might be dark even on dark mode if not set */
+ color: var(--primary-text-color);
outline: none;
width: 100%;
height: 23px;
diff --git a/polygerrit-ui/app/elements/chat-panel/gemini-message.ts b/polygerrit-ui/app/elements/chat-panel/gemini-message.ts
index 701aa1f..8204d4e 100644
--- a/polygerrit-ui/app/elements/chat-panel/gemini-message.ts
+++ b/polygerrit-ui/app/elements/chat-panel/gemini-message.ts
@@ -94,7 +94,7 @@
align-items: center;
}
.gemini-icon {
- color: #4285f4;
+ color: var(--link-color);
}
.thinking-spinner {
--md-circular-progress-size: 24px;
diff --git a/polygerrit-ui/app/elements/chat-panel/splash-page.ts b/polygerrit-ui/app/elements/chat-panel/splash-page.ts
index f7cf759..d28d37c 100644
--- a/polygerrit-ui/app/elements/chat-panel/splash-page.ts
+++ b/polygerrit-ui/app/elements/chat-panel/splash-page.ts
@@ -123,7 +123,7 @@
margin-block-end: var(--spacing-s);
}
.material-icon {
- color: #5f6368;
+ color: var(--deemphasized-text-color);
}
.splash-question {
color: var(--chat-splash-page-question-color);
diff --git a/polygerrit-ui/app/utils/comment-util.ts b/polygerrit-ui/app/utils/comment-util.ts
index a44d2c8..4b0c1ab 100644
--- a/polygerrit-ui/app/utils/comment-util.ts
+++ b/polygerrit-ui/app/utils/comment-util.ts
@@ -717,7 +717,12 @@
if (excludePath.path === SpecialFilePath.PATCHSET_LEVEL_COMMENTS) return '';
if (excludePath.line === FILE) return FILE;
if (excludePath.line) return `#${excludePath.line}`;
- if (excludePath.range) return `#${excludePath.range.end_line}`;
+ if (excludePath.range) {
+ // If the range is wrong, we display the start line. Happens to AI generated comments.
+ if (excludePath.range.end_line < excludePath.range.start_line)
+ return `#${excludePath.range.start_line}`;
+ return `#${excludePath.range.end_line}`;
+ }
return '';
}
diff --git a/polygerrit-ui/app/utils/comment-util_test.ts b/polygerrit-ui/app/utils/comment-util_test.ts
index 61d374b..e8fe606 100644
--- a/polygerrit-ui/app/utils/comment-util_test.ts
+++ b/polygerrit-ui/app/utils/comment-util_test.ts
@@ -730,6 +730,20 @@
);
});
+ test('invalid range', () => {
+ assert.equal(
+ computeDisplayLine({
+ range: {
+ start_line: 12,
+ start_character: 1,
+ end_line: 1,
+ end_character: 10,
+ },
+ }),
+ '#12'
+ );
+ });
+
test('empty', () => {
assert.equal(computeDisplayLine({}), '');
});
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-dark.png
index c7ad776..e1487ec 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations-dark.png
index dac5fa2..9085938 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations.png
index 105a290..709812b 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment-dark.png
index c4f9192..8c05a18 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment.png
index d253819..4dbff42 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error-dark.png
index 14f8b9d..4dc6614 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error.png
index 18a3a1eb..94f87ed 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references-dark.png
index 694df41..db53d9b 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references.png
index 924e634..f56aeac4 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode.png
index 387d1bf..0213343 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions-dark.png
index 7493690..4af3b73 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions.png
index a9c0589..28917ce 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-dark.png
index a888964..1a9152a 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private-dark.png
index 8fcf45d..7bd60ec 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private.png
index 43b6c10..18f3c04 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page.png
index 904a4d4..78b0ef7 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page.png
Binary files differ