init commit

This commit is contained in:
Jan-Peter Klein
2023-05-09 09:00:56 +02:00
parent 532ffb1202
commit b10523ea6c
4 changed files with 226 additions and 6 deletions

View File

@@ -1,10 +1,14 @@
package org.cryptomator.ui.error;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.cryptomator.common.Environment;
import org.cryptomator.common.ErrorCode;
import org.cryptomator.common.Nullable;
import org.cryptomator.ui.common.FxController;
import java.lang.reflect.Type;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.application.Application;
@@ -16,13 +20,33 @@ import javafx.scene.Scene;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.stage.Stage;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import com.google.gson.JsonParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStreamReader;
import java.util.Set;
public class ErrorController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(ErrorController.class);
private static final String ERROR_CODES_URL = "https://gist.githubusercontent.com/cryptobot/accba9fb9555e7192271b85606f97230/raw/errorcodes.json";
private static final String SEARCH_URL_FORMAT = "https://github.com/cryptomator/cryptomator/discussions/categories/errors?discussions_q=category:Errors+%s";
private static final String REPORT_URL_FORMAT = "https://github.com/cryptomator/cryptomator/discussions/new?category=Errors&title=Error+%s&body=%s";
private static final String SEARCH_ERRORCODE_DELIM = " OR ";
@@ -47,6 +71,10 @@ public class ErrorController implements FxController {
private final Environment environment;
private BooleanProperty copiedDetails = new SimpleBooleanProperty();
private BooleanProperty lookUpSolutionVisibility = new SimpleBooleanProperty();
private final HttpClient httpClient;
List<ErrorDiscussion> errorDiscussionList;
@Inject
ErrorController(Application application, @Named("stackTrace") String stackTrace, ErrorCode errorCode, @Nullable Scene previousScene, Stage window, Environment environment) {
@@ -56,6 +84,86 @@ public class ErrorController implements FxController {
this.previousScene = previousScene;
this.window = window;
this.environment = environment;
this.httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build();
HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(URI.create(ERROR_CODES_URL))
.build();
CompletableFuture<HttpResponse<String>> future = httpClient.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString());
future.thenAcceptAsync(response -> {
int statusCode = response.statusCode();
if (statusCode == 200) {
String jsonString = response.body();
//LOG.debug("jpkED - jsonString : " + jsonString);
//System.out.println(jsonString);
//JsonObject jsonObject = (JsonObject)new JsonParser().parse(jsonString);
jsonString = "[{\"id\":\"D_kwDOAPryk84ASwC1\",\"upvoteCount\":4,\"title\":\"Error GH1B:GH1B:NJFJ\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2710\",\"answer\":{\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2710#discussioncomment-5191708\",\"upvoteCount\":3},\"comments\":8},{\"id\":\"D_kwDOAPryk84ASw_I\",\"upvoteCount\":1,\"title\":\"Error GH1B:GH1B:NJFJ\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2716\",\"answer\":null,\"comments\":2},{\"id\":\"D_kwDOAPryk84ASxAg\",\"upvoteCount\":1,\"title\":\"Error GH1B:GH1B:NJFJ\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2717\",\"answer\":{\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2717#discussioncomment-5181996\",\"upvoteCount\":2},\"comments\":3},{\"id\":\"D_kwDOAPryk84ASxDK\",\"upvoteCount\":1,\"title\":\"Error GH1B:GH1B:NJFJ\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2718\",\"answer\":null,\"comments\":0},{\"id\":\"D_kwDOAPryk84ATj-U\",\"upvoteCount\":1,\"title\":\"ErrorCode N05M:GEAO:GEAO\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2877\",\"answer\":null,\"comments\":1},{\"id\":\"D_kwDOAPryk84ATl2o\",\"upvoteCount\":1,\"title\":\"Error GH1B:GH1B:NJFJ\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2883\",\"answer\":{\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2883#discussioncomment-5769879\",\"upvoteCount\":1},\"comments\":1},{\"id\":\"D_kwDOAPryk84ATqCM\",\"upvoteCount\":1,\"title\":\"Error Code 4VHF:1S9S:5EOP\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2887\",\"answer\":null,\"comments\":0},{\"id\":\"D_kwDOAPryk84ATqDF\",\"upvoteCount\":1,\"title\":\"Error H1VR:OTAS:OTAS\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2888\",\"answer\":null,\"comments\":0},{\"id\":\"D_kwDOAPryk84ATrPD\",\"upvoteCount\":1,\"title\":\"Error S4DB:IV2H:I3UI\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2891\",\"answer\":{\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2891#discussioncomment-5797329\",\"upvoteCount\":1},\"comments\":1},{\"id\":\"D_kwDOAPryk84ATtJZ\",\"upvoteCount\":1,\"title\":\"Error 3MAT:BDUS:BDUS\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2894\",\"answer\":null,\"comments\":0},{\"id\":\"D_kwDOAPryk84ATuDc\",\"upvoteCount\":1,\"title\":\"Error QPDR:AFGD:AFGD\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2895\",\"answer\":null,\"comments\":0}]";
Gson gson = new Gson();
Type listType = new TypeToken<List<ErrorDiscussion>>(){}.getType();
errorDiscussionList = gson.fromJson(jsonString,listType);
loadJsonToErrorDiscussionList();
LOG.debug("jpkED - errorDiscussionList loaded | amount:"+errorDiscussionList.size()+"");
//find exact matching
List<ErrorDiscussion> newErrorDiscussionList = new ArrayList<>();
newErrorDiscussionList.addAll(errorDiscussionList);
newErrorDiscussionList.removeIf(errorDiscussion -> !errorDiscussion.getErrorCode().contains(getErrorCode()));
if(newErrorDiscussionList.size()>0){
errorDiscussionList.clear();
errorDiscussionList.addAll(newErrorDiscussionList);
LOG.debug("jpkED - exact match | amount:"+errorDiscussionList.size()+"");
lookUpSolutionVisibility.set(true);
}
else{
//find method code matching
newErrorDiscussionList.clear();
newErrorDiscussionList.addAll(errorDiscussionList);
newErrorDiscussionList.removeIf(errorDiscussion -> !errorDiscussion.getErrorCode().contains(getErrorCodeMethodCode()));
if(newErrorDiscussionList.size()>0){
errorDiscussionList.clear();
errorDiscussionList.addAll(newErrorDiscussionList);
LOG.debug("jpkED - method match | amount:"+errorDiscussionList.size()+"");
}
else{
errorDiscussionList.clear();
LOG.debug("jpkED - nothing found");
}
}
if(errorDiscussionList.size()!=0){
//answered
newErrorDiscussionList.clear();
newErrorDiscussionList.addAll(errorDiscussionList);
newErrorDiscussionList.removeIf(errorDiscussion -> errorDiscussion.answer == null);
if(newErrorDiscussionList.size()>0){
errorDiscussionList.clear();
errorDiscussionList.addAll(newErrorDiscussionList);
LOG.debug("jpkED - answered | amount:"+errorDiscussionList.size()+"");
}
Collections.sort(errorDiscussionList, this::errorDiscussionComparator);
LOG.debug("jpkED - most upvote | id: " + errorDiscussionList.get(0).id + " | title: " + errorDiscussionList.get(0).title + " | upvoteCount:" + errorDiscussionList.get(0).upvoteCount);
}
}
}).join();
}
@FXML
@@ -70,6 +178,13 @@ public class ErrorController implements FxController {
window.close();
}
@FXML
public void showSolution() {
if(errorDiscussionList.size()!=0) {
application.getHostServices().showDocument(errorDiscussionList.get(0).url);
}
}
@FXML
public void searchError() {
var searchTerm = URLEncoder.encode(getErrorCode().replace(ErrorCode.DELIM, SEARCH_ERRORCODE_DELIM), StandardCharsets.UTF_8);
@@ -111,7 +226,11 @@ public class ErrorController implements FxController {
}
public String getErrorCode() {
return errorCode.toString();
//return "GH1B:GH1B:NJFJ"; // 31 exact match - 4 answered
//return "GIJU:E215:E215"; // 1 exact match - 0 answered
//return "6PHE:UG0C:UG0C"; // 0 exact match - 8 method match - 3 answered
//return "0000:0000:0000"; // 0 match
return errorCode.toString(); // 0 exact match - 8 method match - 3 answered
}
public String getDetailText() {
@@ -125,4 +244,65 @@ public class ErrorController implements FxController {
public boolean getCopiedDetails() {
return copiedDetails.get();
}
}
public BooleanProperty lookUpSolutionVisibilityProperty() {
return lookUpSolutionVisibility;
}
public boolean getLookUpSolutionVisibility() {
return lookUpSolutionVisibility.get();
}
public String getDetailTexts() {
return "```\nError Code " + getErrorCode() + "\n" + getStackTrace() + "\n```";
}
private void filterListByMethodCode(){
List<ErrorDiscussion> newErrorDiscussionList = new ArrayList<>();
for (int i = 0; i < errorDiscussionList.size(); i++) {
ErrorDiscussion errorDiscussion = errorDiscussionList.get(i);
if(errorDiscussion.getMethodCode().equals(getErrorCodeMethodCode())){
newErrorDiscussionList.add(errorDiscussion);
}
}
if(newErrorDiscussionList.size()!=0){
errorDiscussionList = newErrorDiscussionList;
lookUpSolutionVisibility.set(true);
LOG.debug("jpkED - found matching method code | amount:"+errorDiscussionList.size()+"");
}
else{
errorDiscussionList = newErrorDiscussionList; // to clear results
LOG.debug("jpkED - no matching method code found");
}
}
private int errorDiscussionComparator(ErrorDiscussion t, ErrorDiscussion t1) {
return Integer.compare(t1.upvoteCount, t.upvoteCount);
}
private String getErrorCodeMethodCode(){
return getErrorCode().substring(0,4);
}
private void loadJsonToErrorDiscussionList(){
String errorCodesUrl = "https://gist.githubusercontent.com/cryptobot/accba9fb9555e7192271b85606f97230/raw/errorcodes.json";
try (InputStream is = new URL(errorCodesUrl).openStream()) { //TODO: HttpClient(){ async request
JsonObject jsonObject = (JsonObject)new JsonParser().parse(new InputStreamReader(is,"UTF-8"));
LOG.debug("jpkED - jsonObject | "+jsonObject.toString());
Set<String> keys = jsonObject.keySet();
errorDiscussionList = new ArrayList<>();
for (int i = 0; i < jsonObject.size(); i++) {
errorDiscussionList.add(new Gson().fromJson(jsonObject.get(keys.stream().toList().get(i)),ErrorDiscussion.class));
}
LOG.debug("jpkED - errorDiscussionList loaded | amount:"+errorDiscussionList.size()+"");
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,31 @@
package org.cryptomator.ui.error;
public class ErrorDiscussion {
String id;
int upvoteCount;
String title;
String url;
int comments;
Answer answer;
String getUpvoteCount(){return upvoteCount+"";}
String getErrorCode(){return title.substring(6);}
String getMethodCode(){
return title.substring(6,10);
}
String getRootCauseCode(){
return title.substring(11,15);
}
String getThrowableCode(){
return title.substring(16,20);
}
class Answer{
private String url;
private int upvoteCount;
}
}

View File

@@ -31,13 +31,19 @@
</StackPane>
<VBox spacing="6" HBox.hgrow="ALWAYS">
<FormattedLabel styleClass="label-extra-large" format="%error.message" arg1="${controller.errorCode}"/>
<Label text="%error.description" wrapText="true"/>
<Hyperlink styleClass="hyperlink-underline" text="%error.hyperlink.lookup" onAction="#searchError" contentDisplay="LEFT">
<Label text="%error.existingSolutionDescription" wrapText="true" visible="${controller.lookUpSolutionVisibility}" managed="${controller.lookUpSolutionVisibility}"/>
<Label text="%error.description" wrapText="true" visible="${!controller.lookUpSolutionVisibility}" managed="${!controller.lookUpSolutionVisibility}"/>
<Hyperlink styleClass="hyperlink-underline" text="%error.hyperlink.solution" onAction="#showSolution" contentDisplay="LEFT" visible="${controller.lookUpSolutionVisibility}" managed="${controller.lookUpSolutionVisibility}">
<graphic>
<FontAwesome5IconView glyph="LINK" glyphSize="12"/>
</graphic>
</Hyperlink>
<Hyperlink styleClass="hyperlink-underline" text="%error.hyperlink.report" onAction="#reportError" contentDisplay="LEFT">
<Hyperlink styleClass="hyperlink-underline" text="%error.hyperlink.lookup" onAction="#searchError" contentDisplay="LEFT" visible="${!controller.lookUpSolutionVisibility}" managed="${!controller.lookUpSolutionVisibility}">
<graphic>
<FontAwesome5IconView glyph="LINK" glyphSize="12"/>
</graphic>
</Hyperlink>
<Hyperlink styleClass="hyperlink-underline" text="%error.hyperlink.report" onAction="#reportError" contentDisplay="LEFT" visible="${!controller.lookUpSolutionVisibility}" managed="${!controller.lookUpSolutionVisibility}">
<graphic>
<FontAwesome5IconView glyph="LINK" glyphSize="12"/>
</graphic>
@@ -60,7 +66,7 @@
</graphic>
</Hyperlink>
</HBox>
<TextArea VBox.vgrow="ALWAYS" text="${controller.detailText}" prefRowCount="5" editable="false"/>
<TextArea VBox.vgrow="ALWAYS" text="${controller.detailTexts}" prefRowCount="5" editable="false"/>
</VBox>
<ButtonBar buttonMinWidth="120" buttonOrder="B+C">

View File

@@ -21,6 +21,9 @@ error.description=Cryptomator didn't expect this to happen. You can look up exis
error.hyperlink.lookup=Look up this error
error.hyperlink.report=Report this error
error.technicalDetails=Details:
error.existingSolutionDescription=Cryptomator didn't expect this to happen. But we found an existing solution for this error. Please take a look at the following link.
error.hyperlink.solution=Look up the solution
# Defaults
defaults.vault.vaultName=Vault