Skip to content

Commit ad08227

Browse files
authored
Merge pull request #24 from InAnYan/fix-for-issue-20
2 parents 284a050 + 2675b56 commit ad08227

File tree

6 files changed

+185
-7
lines changed

6 files changed

+185
-7
lines changed

src/main/java/org/jabref/gui/entryeditor/EntryEditor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ private List<EntryEditorTab> createTabs() {
321321
entryEditorTabs.add(sourceTab);
322322
entryEditorTabs.add(new LatexCitationsTab(databaseContext, preferencesService, dialogService, directoryMonitorManager));
323323
entryEditorTabs.add(new FulltextSearchResultsTab(stateManager, preferencesService, dialogService, taskExecutor));
324-
entryEditorTabs.add(new AiChatTab(preferencesService, aiService, databaseContext, taskExecutor));
324+
entryEditorTabs.add(new AiChatTab(dialogService, preferencesService, aiService, databaseContext, taskExecutor));
325325

326326
return entryEditorTabs;
327327
}

src/main/java/org/jabref/gui/entryeditor/aichattab/AiChatTab.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55

66
import javafx.scene.control.*;
77

8+
import org.jabref.gui.DialogService;
89
import org.jabref.gui.entryeditor.EntryEditorPreferences;
910
import org.jabref.gui.entryeditor.EntryEditorTab;
1011
import org.jabref.gui.entryeditor.aichattab.components.aichat.AiChatComponent;
12+
import org.jabref.gui.entryeditor.aichattab.components.errorstate.ErrorStateComponent;
13+
import org.jabref.gui.entryeditor.aichattab.components.privacynotice.PrivacyNoticeComponent;
1114
import org.jabref.gui.util.BackgroundTask;
1215
import org.jabref.gui.util.TaskExecutor;
1316
import org.jabref.logic.ai.AiChat;
@@ -37,6 +40,7 @@ public class AiChatTab extends EntryEditorTab {
3740
Answer the question only by using the relevant information. Don't make up the answer.
3841
If you can't answer the user question using the provided information, then reply that you couldn't do it.""";
3942

43+
private final DialogService dialogService;
4044
private final FilePreferences filePreferences;
4145
private final AiPreferences aiPreferences;
4246
private final EntryEditorPreferences entryEditorPreferences;
@@ -51,8 +55,9 @@ public class AiChatTab extends EntryEditorTab {
5155

5256
private BibEntry currentBibEntry = null;
5357

54-
public AiChatTab(PreferencesService preferencesService, AiService aiService,
58+
public AiChatTab(DialogService dialogService, PreferencesService preferencesService, AiService aiService,
5559
BibDatabaseContext bibDatabaseContext, TaskExecutor taskExecutor) {
60+
this.dialogService = dialogService;
5661
this.filePreferences = preferencesService.getFilePreferences();
5762
this.aiPreferences = preferencesService.getAiPreferences();
5863
this.entryEditorPreferences = preferencesService.getEntryEditorPreferences();
@@ -75,15 +80,17 @@ public boolean shouldShow(BibEntry entry) {
7580
@Override
7681
protected void bindToEntry(BibEntry entry) {
7782
if (!aiPreferences.getEnableChatWithFiles()) {
78-
setContent(new Label(Localization.lang("JabRef uses OpenAI to enable \"chatting\" with PDF files. OpenAI is an external service. To enable JabRef chatgting with PDF files, the content of the PDF files need to be shared with OpenAI. As soon as you ask a question, the text content of all PDFs attached to the entry are send to OpenAI. The privacy policy of OpenAI applies. You find it at <https://openai.com/policies/privacy-policy/>.")));
83+
setContent(new PrivacyNoticeComponent(dialogService, aiPreferences, filePreferences, () -> {
84+
bindToEntry(entry);
85+
}));
7986
} else if (entry.getCitationKey().isEmpty()) {
80-
setContent(new Label(Localization.lang("Please provide a citation key for the entry in order to enable chatting with PDF files.")));
87+
setContent(new ErrorStateComponent(Localization.lang("Error"), Localization.lang("Please provide a citation key for the entry in order to enable chatting with PDF files.")));
8188
} else if (!checkIfCitationKeyIsUnique(bibDatabaseContext, entry.getCitationKey().get())) {
82-
setContent(new Label(Localization.lang("Please provide a unique citation key for the entry in order to enable chatting with PDF files.")));
89+
setContent(new ErrorStateComponent(Localization.lang("Error"), Localization.lang("Please provide a unique citation key for the entry in order to enable chatting with PDF files.")));
8390
} else if (entry.getFiles().isEmpty()) {
84-
setContent(new Label(Localization.lang("No files attached")));
91+
setContent(new ErrorStateComponent(Localization.lang("Unable to chat"), Localization.lang("Please attach at least one PDF file to enable chatting with PDF files.")));
8592
} else if (!entry.getFiles().stream().map(LinkedFile::getLink).map(Path::of).allMatch(FileUtil::isPDFFile)) {
86-
setContent(new Label(Localization.lang("Only PDF files are supported")));
93+
setContent(new ErrorStateComponent(Localization.lang("Unable to chat"), Localization.lang("Only PDF files are supported")));
8794
} else {
8895
bindToCorrectEntry(entry);
8996
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<?import javafx.geometry.*?>
4+
<?import javafx.scene.layout.*?>
5+
<?import javafx.scene.text.*?>
6+
7+
<fx:root type="Pane" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.jabref.gui.entryeditor.aichattab.components.errorstate.ErrorStateComponent">
8+
<children>
9+
<VBox spacing="10.0">
10+
<children>
11+
<Text fx:id="titleText" strokeType="OUTSIDE" strokeWidth="0.0" text="Title">
12+
<font>
13+
<Font name="System Bold" size="24.0" />
14+
</font>
15+
</Text>
16+
<Text fx:id="contentText" strokeType="OUTSIDE" strokeWidth="0.0" text="Content">
17+
<font>
18+
<Font size="14.0" />
19+
</font>
20+
</Text>
21+
</children>
22+
<padding>
23+
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
24+
</padding>
25+
</VBox>
26+
</children>
27+
</fx:root>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.jabref.gui.entryeditor.aichattab.components.errorstate;
2+
3+
import javafx.fxml.FXML;
4+
import javafx.scene.layout.Pane;
5+
import javafx.scene.text.Text;
6+
7+
import com.airhacks.afterburner.views.ViewLoader;
8+
9+
public class ErrorStateComponent extends Pane {
10+
@FXML private Text titleText;
11+
@FXML private Text contentText;
12+
13+
public ErrorStateComponent(String title, String content) {
14+
ViewLoader.view(this)
15+
.root(this)
16+
.load();
17+
18+
setTitle(title);
19+
setContent(content);
20+
}
21+
22+
public String getTitle() {
23+
return titleText.getText();
24+
}
25+
26+
public void setTitle(String title) {
27+
titleText.setText(title);
28+
}
29+
30+
public String getContent() {
31+
return contentText.getText();
32+
}
33+
34+
public void setContent(String content) {
35+
contentText.setText(content);
36+
}
37+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<?import javafx.geometry.*?>
4+
<?import javafx.scene.control.*?>
5+
<?import javafx.scene.layout.*?>
6+
<?import javafx.scene.text.*?>
7+
8+
<fx:root type="Pane" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.jabref.gui.entryeditor.aichattab.components.privacynotice.PrivacyNoticeComponent">
9+
<children>
10+
<VBox spacing="10.0">
11+
<padding>
12+
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
13+
</padding>
14+
<children>
15+
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="%Privacy notice">
16+
<font>
17+
<Font name="System Bold" size="24.0" />
18+
</font>
19+
</Text>
20+
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="%JabRef uses OpenAI to enable &quot;chatting&quot; with PDF files. OpenAI is an external service. To enable JabRef chatgting with PDF files, the content of the PDF files need to be shared with OpenAI.">
21+
<font>
22+
<Font size="14.0" />
23+
</font>
24+
</Text>
25+
<Text layoutX="20.0" layoutY="77.0" strokeType="OUTSIDE" strokeWidth="0.0" text="%As soon as you ask a question, the text content of all PDFs attached to the entry are send to OpenAI.">
26+
<font>
27+
<Font size="14.0" />
28+
</font>
29+
</Text>
30+
<TextFlow>
31+
<children>
32+
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="%The privacy policy of OpenAI applies. You find it at">
33+
<font>
34+
<Font size="14.0" />
35+
</font>
36+
</Text>
37+
<Hyperlink onAction="#onPrivacyHyperlinkClick" text="https://openai.com/policies/privacy-policy/">
38+
<font>
39+
<Font size="14.0" />
40+
</font>
41+
</Hyperlink>
42+
</children>
43+
</TextFlow>
44+
<Button mnemonicParsing="false" onAction="#onIAgreeButtonClick" text="%I agree">
45+
<font>
46+
<Font size="14.0" />
47+
</font>
48+
</Button>
49+
</children>
50+
</VBox>
51+
</children>
52+
</fx:root>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package org.jabref.gui.entryeditor.aichattab.components.privacynotice;
2+
3+
import java.io.IOException;
4+
5+
import javafx.fxml.FXML;
6+
import javafx.scene.layout.Pane;
7+
8+
import org.jabref.gui.DialogService;
9+
import org.jabref.gui.desktop.JabRefDesktop;
10+
import org.jabref.preferences.AiPreferences;
11+
import org.jabref.preferences.FilePreferences;
12+
13+
import com.airhacks.afterburner.views.ViewLoader;
14+
15+
import org.slf4j.Logger;
16+
import org.slf4j.LoggerFactory;
17+
18+
public class PrivacyNoticeComponent extends Pane {
19+
private final Logger LOGGER = LoggerFactory.getLogger(PrivacyNoticeComponent.class);
20+
21+
private final DialogService dialogService;
22+
23+
private final AiPreferences aiPreferences;
24+
private final FilePreferences filePreferences;
25+
26+
private final Runnable onIAgreeButtonClickCallback;
27+
28+
public PrivacyNoticeComponent(DialogService dialogService, AiPreferences aiPreferences, FilePreferences filePreferences, Runnable onIAgreeButtonClickCallback) {
29+
this.dialogService = dialogService;
30+
this.aiPreferences = aiPreferences;
31+
this.filePreferences = filePreferences;
32+
33+
this.onIAgreeButtonClickCallback = onIAgreeButtonClickCallback;
34+
35+
ViewLoader.view(this)
36+
.root(this)
37+
.load();
38+
}
39+
40+
@FXML
41+
private void onPrivacyHyperlinkClick() {
42+
try {
43+
JabRefDesktop.openBrowser("https://openai.com/policies/privacy-policy/", filePreferences);
44+
} catch (IOException e) {
45+
LOGGER.error("Error opening the browser to OpenAI privacy policy page.", e);
46+
dialogService.showErrorDialogAndWait(e);
47+
}
48+
}
49+
50+
@FXML
51+
private void onIAgreeButtonClick() {
52+
aiPreferences.setEnableChatWithFiles(true);
53+
onIAgreeButtonClickCallback.run();
54+
}
55+
}

0 commit comments

Comments
 (0)