Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/io/flutter/FlutterInitializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import io.flutter.run.FlutterReloadManager;
import io.flutter.run.FlutterRunNotifications;
import io.flutter.run.daemon.DeviceService;
import io.flutter.samples.FlutterSampleManager;
import io.flutter.sdk.FlutterPluginsLibraryManager;
import io.flutter.settings.FlutterSettings;
import io.flutter.utils.FlutterModuleUtils;
Expand Down Expand Up @@ -123,6 +124,9 @@ public void runActivity(@NotNull Project project) {
// Start the widget perf manager.
FlutterWidgetPerfManager.init(project);

// Load the sample index.
FlutterSampleManager.initialize(project);

// Watch save actions for reload on save.
FlutterReloadManager.init(project);

Expand Down
5 changes: 2 additions & 3 deletions src/io/flutter/module/FlutterModuleBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ public class FlutterModuleBuilder extends ModuleBuilder {
private static final Logger LOG = Logger.getInstance(FlutterModuleBuilder.class);

private FlutterModuleWizardStep myStep;
@NotNull
private final FlutterCreateAdditionalSettingsFields mySettingsFields =
new FlutterCreateAdditionalSettingsFields(new FlutterCreateAdditionalSettings());
private FlutterCreateAdditionalSettingsFields mySettingsFields;

@Override
public String getName() {
Expand Down Expand Up @@ -258,6 +256,7 @@ public ModuleWizardStep modifyProjectTypeStep(@NotNull SettingsStep settingsStep
@Override
public ModuleWizardStep getCustomOptionsStep(final WizardContext context, final Disposable parentDisposable) {
myStep = new FlutterModuleWizardStep(context);
mySettingsFields = new FlutterCreateAdditionalSettingsFields(new FlutterCreateAdditionalSettings(), myStep.getFlutterSdk());
Disposer.register(parentDisposable, myStep);
return myStep;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.flutter.FlutterBundle;
import io.flutter.module.FlutterProjectType;
import io.flutter.sdk.FlutterCreateAdditionalSettings;
import io.flutter.sdk.FlutterSdk;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
Expand All @@ -26,15 +27,14 @@ public class FlutterCreateAdditionalSettingsFields {
private final RadiosForm iosLanguageRadios;
private final ProjectType projectTypeForm;
private final FlutterCreateParams createParams;

public FlutterCreateAdditionalSettingsFields() {
this(new FlutterCreateAdditionalSettings());
this(new FlutterCreateAdditionalSettings(), null);
}

public FlutterCreateAdditionalSettingsFields(FlutterCreateAdditionalSettings additionalSettings) {
public FlutterCreateAdditionalSettingsFields(FlutterCreateAdditionalSettings additionalSettings, FlutterSdk sdk) {
settings = additionalSettings;

projectTypeForm = new ProjectType();
projectTypeForm = new ProjectType(sdk);
projectTypeForm.addListener(e -> {
settings.setType(projectTypeForm.getType());
settings.setSampleContent(projectTypeForm.getSample());
Expand Down
19 changes: 16 additions & 3 deletions src/io/flutter/module/settings/ProjectType.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@
import io.flutter.FlutterBundle;
import io.flutter.module.FlutterProjectType;
import io.flutter.samples.FlutterSample;
import io.flutter.samples.FlutterSampleManager;
import io.flutter.sdk.FlutterSdk;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;

Expand Down Expand Up @@ -66,10 +67,15 @@ public void setSelectedItem(FlutterProjectType item) {

private static final class FlutterSampleComboBoxModel extends AbstractListModel<FlutterSample>
implements ComboBoxModel<FlutterSample> {
private final List<FlutterSample> myList = FlutterSampleManager.getSamples();
private final List<FlutterSample> myList;
private FlutterSample mySelected;

public FlutterSampleComboBoxModel() {
this(null);
}

public FlutterSampleComboBoxModel(@Nullable FlutterSdk sdk) {
myList = sdk == null ? Collections.emptyList() : sdk.getSamples();
mySelected = myList.isEmpty() ? null : myList.get(0);
}

Expand Down Expand Up @@ -112,11 +118,18 @@ protected void customizeCellRenderer(@NotNull JList<? extends FlutterSample> lis
}
}

@Nullable
private final FlutterSdk sdk;

private JPanel projectTypePanel;
private ComboBox projectTypeCombo;
private ComboBox<FlutterSample> snippetSelectorCombo;
private JCheckBox generateSampleContentCheckBox;

public ProjectType(@Nullable FlutterSdk sdk) {
this.sdk = sdk;
}

private void createUIComponents() {
projectTypeCombo = new ComboBox<>();
//noinspection unchecked
Expand All @@ -132,7 +145,7 @@ private void createUIComponents() {
});

snippetSelectorCombo = new ComboBox<>();
snippetSelectorCombo.setModel(new FlutterSampleComboBoxModel());
snippetSelectorCombo.setModel(new FlutterSampleComboBoxModel(sdk));
snippetSelectorCombo.setRenderer(new FlutterSampleCellRenderer());
snippetSelectorCombo.setToolTipText(FlutterBundle.message("flutter.module.create.settings.sample.tip"));
snippetSelectorCombo.setEnabled(false);
Expand Down
26 changes: 21 additions & 5 deletions src/io/flutter/samples/FlutterSample.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,23 @@ public String toString() {
* Get a label suitable for display in a chooser (e.g., combobox).
*/
public String getDisplayLabel() {
// TODO(pq): add disambiguation once it's needed.
// TODO(pq): come up with disambiguated labels.
// TODO(pq): consider adding (package suffix too).
// Index isn't quite enough for disambiguation (there are still dups like DeletableChips).
//final String[] parts = id.split("\\.");
//final String lastPart = parts[parts.length-1];
//
//String suffix = "";
//try {
// final int index = Integer.parseInt(lastPart);
// if (index != 1) {
// suffix = " (" + index + ")";
// }
//} catch (NumberFormatException e) {
// // ignore
//}
//
//return getElement() + suffix;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming you want to keep all the above in case it is useful solving the TODOs. If you just forgot about it, then here's a reminder to delete it. :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentional. But thanks!

return getElement();
}

Expand Down Expand Up @@ -71,19 +87,19 @@ public static String parseHtmlDescription(@NotNull String description) {

// Remove links: [Card] => **Card**
final StringBuilder builder = new StringBuilder();
for (int i=0; i < description.length(); ++i) {
for (int i = 0; i < description.length(); ++i) {
final char c = description.charAt(i);
if ((c == '[' || c == ']') && (i == 0 || description.charAt(i-1) != '\\')) {
if ((c == '[' || c == ']') && (i == 0 || description.charAt(i - 1) != '\\')) {
builder.append("**");
} else {
}
else {
builder.append(c);
}
}

return new MarkdownProcessor().markdown(builder.toString()).trim();
}


@NotNull
public String getLibrary() {
return library;
Expand Down
4 changes: 0 additions & 4 deletions src/io/flutter/samples/FlutterSampleComboBox.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ protected void customizeCellRenderer(@NotNull JList<? extends FlutterSample> lis
}
}

FlutterSampleComboBox() {
this(FlutterSampleManager.getSamples());
}

FlutterSampleComboBox(@NotNull List<FlutterSample> samples) {
super(new SampleModel(samples));
setRenderer(new SampleCellRenderer());
Expand Down
117 changes: 92 additions & 25 deletions src/io/flutter/samples/FlutterSampleManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.OutputListener;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.openapi.diagnostic.Logger;
Expand All @@ -32,31 +36,112 @@
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class FlutterSampleManager {
// TODO(pq): remove after testing.
// See https://github.com/flutter/flutter-intellij/issues/3330.
private static final boolean DISABLE_SAMPLES = true;
private static final boolean DISABLE_SAMPLES = false;

private static final String SNIPPETS_REMOTE_INDEX_URL = "https://docs.flutter.io/snippets/index.json";

private static final Logger LOG = Logger.getInstance(FlutterSampleManager.class);
@NotNull
private final FlutterSdk sdk;

private static List<FlutterSample> SAMPLES;
private List<FlutterSample> flutterSamples;

public static List<FlutterSample> getSamples() {
public FlutterSampleManager(@NotNull FlutterSdk sdk) {
this.sdk = sdk;
}

public List<FlutterSample> getSamples() {
if (DISABLE_SAMPLES) {
return Collections.emptyList();
}

if (SAMPLES == null) {
// When we're reading from the repo and the file may be changing, consider a fresh read on each access.
SAMPLES = loadSamples();
if (flutterSamples != null) {
return flutterSamples;
}

try {
final File tempDir = Files.createTempDirectory("flutter-samples-index").toFile();
tempDir.deleteOnExit();
final File tempFile = new File(tempDir, "index.json");

try {
final GeneralCommandLine commandLine = sdk.flutterListSamples(tempFile).createGeneralCommandLine(null);
LOG.info(commandLine.toString());
final OSProcessHandler process = new OSProcessHandler(commandLine);
process.addProcessListener(new ProcessAdapter() {
@Override
public void processTerminated(@NotNull ProcessEvent event) {
try {
final byte[] bytes = Files.readAllBytes(tempFile.toPath());
final String content = new String(bytes);
flutterSamples = FlutterSampleManager.readSamples(content);
}
catch (IOException e) {
LOG.warn(e);
// On IOException, short circuit checking again.
flutterSamples = Collections.emptyList();
}
}
});

process.startNotify();

final int timeoutInMs = 2000;
// TODO(pq): is this wait right?
if (process.waitFor(timeoutInMs)) {
LOG.info("Flutter sample listing took more than " + timeoutInMs + "ms");
// Don't cache here so that we can try again later.
}
}
catch (ExecutionException e) {
LOG.warn(e);
// On ExecutionException, short circuit checking again.
flutterSamples = Collections.emptyList();
}
}
return SAMPLES;
catch (IOException e) {
LOG.warn(e);
// On IOException, short circuit checking again.
flutterSamples = Collections.emptyList();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the network is unreliable, will the IDE have to be restarted to reset flutterSamples?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to look into this some more. There are a few wrinkles.

Thanks!

}

return flutterSamples != null ? flutterSamples : Collections.emptyList();
}

// Called at project initialization.
public static void initialize(Project project) {
final FlutterSdk sdk = FlutterSdk.getFlutterSdk(project);
if (sdk != null) {
// Trigger a sample listing.
sdk.getSamples();
}
}

public static List<FlutterSample> readSamples(String indexFileContents) {
final List<FlutterSample> samples = new ArrayList<>();
final JsonArray json = new JsonParser().parse(indexFileContents).getAsJsonArray();
for (JsonElement element : json) {
final JsonObject sample = element.getAsJsonObject();
samples.add(new FlutterSample(sample.getAsJsonPrimitive("element").getAsString(),
sample.getAsJsonPrimitive("library").getAsString(),
sample.getAsJsonPrimitive("id").getAsString(),
sample.getAsJsonPrimitive("file").getAsString(),
sample.getAsJsonPrimitive("sourcePath").getAsString(),
sample.getAsJsonPrimitive("description").getAsString()));
}

// Sort by display label.
samples.sort(Comparator.comparing(FlutterSample::getDisplayLabel));
return samples;
}

private static JsonArray readSampleIndex(final URL sampleUrl) throws IOException {
Expand Down Expand Up @@ -87,24 +172,6 @@ private static JsonArray readSampleIndex() {
return new JsonArray();
}

private static List<FlutterSample> loadSamples() {
final List<FlutterSample> samples = new ArrayList<>();
final JsonArray jsonArray = readSampleIndex();
for (JsonElement element : jsonArray) {
final JsonObject sample = element.getAsJsonObject();
samples.add(new FlutterSample(sample.getAsJsonPrimitive("element").getAsString(),
sample.getAsJsonPrimitive("library").getAsString(),
sample.getAsJsonPrimitive("id").getAsString(),
sample.getAsJsonPrimitive("file").getAsString(),
sample.getAsJsonPrimitive("sourcePath").getAsString(),
sample.getAsJsonPrimitive("description").getAsString()));
}

// Sort by display label.
samples.sort(Comparator.comparing(FlutterSample::getDisplayLabel));
return samples;
}

public static String createSampleProject(@NotNull FlutterSample sample, @NotNull Project project) {
final FlutterSdk sdk = FlutterSdk.getFlutterSdk(project);
if (sdk == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ private List<FlutterSample> getSamplesForFile(@NotNull VirtualFile file) {
final String pathSuffix = FileUtil.normalize(sdk.getHomePath()) + "/packages/flutter/";

final List<FlutterSample> samples = new ArrayList<>();
for (FlutterSample sample : FlutterSampleManager.getSamples()) {
for (FlutterSample sample : sdk.getSamples()) {
final String samplePath = pathSuffix + sample.getSourcePath();
if (filePath.equals(samplePath)) {
samples.add(sample);
Expand Down
1 change: 1 addition & 0 deletions src/io/flutter/sdk/FlutterCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ enum Type {
CONFIG("Flutter config", "config"),
CREATE("Flutter create", "create"),
DOCTOR("Flutter doctor", "doctor", "--verbose"),
LIST_SAMPLES("Flutter create --lists-samples", "create", "--list-samples"),
MAKE_HOST_APP_EDITABLE("Flutter make-host-app-editable", "make-host-app-editable"),
PACKAGES_GET("Flutter packages get", "packages", "get"),
PACKAGES_UPGRADE("Flutter packages upgrade", "packages", "upgrade"),
Expand Down
Loading