base layout extensionstore

This commit is contained in:
sirjonasxx 2021-08-19 03:55:20 +02:00
parent ef3fe01a32
commit 01554eb428
44 changed files with 1962 additions and 19 deletions

View File

@ -51,4 +51,16 @@ public class OSValidator {
}
}
public static String getOSFull() {
if (isWindows()) {
return "Windows";
} else if (isMac()) {
return "Max";
} else if (isUnix()) {
return "Linux";
} else {
return "err";
}
}
}

View File

@ -5,6 +5,8 @@ import gearth.services.extension_handler.extensions.extensionproducers.Extension
import gearth.services.extension_handler.extensions.extensionproducers.ExtensionProducerObserver;
import gearth.services.internal_extensions.blockreplacepackets.BlockAndReplacePackets;
import gearth.services.internal_extensions.blockreplacepackets.BlockAndReplacePacketsLauncher;
import gearth.services.internal_extensions.extensionstore.GExtensionStore;
import gearth.services.internal_extensions.extensionstore.GExtensionStoreLauncher;
import gearth.services.internal_extensions.packetinfoexplorer.PacketInfoExplorer;
import gearth.services.internal_extensions.packetinfoexplorer.PacketInfoExplorerLauncher;
@ -16,6 +18,9 @@ public class SimpleExtensionProducer implements ExtensionProducer {
// uncomment the next line if you want to see an embedded example extension in G-Earth
// observer.onExtensionProduced(new ExampleExtension());
new InternalExtensionFormBuilder<GExtensionStoreLauncher, GExtensionStore>()
.launch(new GExtensionStoreLauncher(), observer);
new InternalExtensionFormBuilder<BlockAndReplacePacketsLauncher, BlockAndReplacePackets>()
.launch(new BlockAndReplacePacketsLauncher(), observer);

View File

@ -1,5 +1,59 @@
package gearth.services.internal_extensions.extensionstore;
public class GExtensionStore {
import gearth.extensions.ExtensionForm;
import gearth.extensions.ExtensionInfo;
import gearth.services.internal_extensions.extensionstore.application.GExtensionStoreController;
import gearth.services.internal_extensions.extensionstore.application.entities.queriedoverviews.ByDateOverview;
import gearth.services.internal_extensions.extensionstore.repository.StoreFetch;
import gearth.services.internal_extensions.extensionstore.repository.StoreRepository;
@ExtensionInfo(
Title = "G-ExtensionStore",
Description = "Get your extensions here",
Version = "1.0",
Author = "sirjonasxx"
)
public class GExtensionStore extends ExtensionForm {
public static final int PAGESIZE = 20;
private StoreRepository repository = null;
private GExtensionStoreController extensionStoreController = null;
public GExtensionStore() {
StoreFetch.fetch(new StoreFetch.StoreFetchListener() {
@Override
public void success(StoreRepository storeRepository) {
repository = storeRepository;
if (extensionStoreController != null) {
extensionStoreController.maybeInitialized();
}
}
@Override
public void fail(String reason) {
System.out.println("failed fetching store repository");
}
});
}
public void setgExtensionStoreController(GExtensionStoreController gExtensionStoreController) {
this.extensionStoreController = gExtensionStoreController;
gExtensionStoreController.maybeInitialized();
}
public GExtensionStoreController getExtensionStoreController() {
return extensionStoreController;
}
public StoreRepository getRepository() {
return repository;
}
@Override
protected boolean canLeave() {
return false;
}
}

View File

@ -0,0 +1,40 @@
package gearth.services.internal_extensions.extensionstore;
import gearth.Main;
import gearth.extensions.InternalExtensionFormLauncher;
import gearth.services.internal_extensions.extensionstore.application.GExtensionStoreController;
import gearth.ui.GEarthController;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
public class GExtensionStoreLauncher extends InternalExtensionFormLauncher<GExtensionStore> {
@Override
public GExtensionStore createForm(Stage stage) throws Exception {
FXMLLoader loader = new FXMLLoader(GExtensionStoreController.class.getResource("gextensionstore.fxml"));
Parent root = loader.load();
// stage.getIcons().add(new Image(GExtensionStoreController.class.getResourceAsStream("webview/images/logo.png")));
stage.setTitle("G-ExtensionStore");
stage.setMinWidth(420);
stage.setMinHeight(500);
stage.setWidth(550);
stage.setHeight(530);
stage.setScene(new Scene(root));
stage.getScene().getStylesheets().add(GEarthController.class.getResource("/gearth/ui/bootstrap3.css").toExternalForm());
stage.getIcons().add(new Image(Main.class.getResourceAsStream("G-EarthLogoSmaller.png")));
GExtensionStore gExtensionStore = new GExtensionStore();
GExtensionStoreController gExtensionStoreController = loader.getController();
gExtensionStore.setgExtensionStoreController(gExtensionStoreController);
gExtensionStoreController.gExtensionStore(gExtensionStore);
return gExtensionStore;
}
}

View File

@ -0,0 +1,231 @@
package gearth.services.internal_extensions.extensionstore.application;
import gearth.services.internal_extensions.extensionstore.GExtensionStore;
import gearth.services.internal_extensions.extensionstore.application.entities.ContentItem;
import gearth.services.internal_extensions.extensionstore.application.entities.HOverview;
import gearth.services.internal_extensions.extensionstore.application.entities.categories.CategoryOverview;
import gearth.services.internal_extensions.extensionstore.application.entities.installed.InstalledOverview;
import gearth.services.internal_extensions.extensionstore.application.entities.queriedoverviews.ByDateOverview;
import gearth.services.internal_extensions.extensionstore.application.entities.queriedoverviews.ByRatingOverview;
import gearth.services.internal_extensions.extensionstore.application.entities.search.SearchOverview;
import gearth.services.internal_extensions.extensionstore.repository.StoreRepository;
import javafx.application.Platform;
import javafx.concurrent.Worker;
import javafx.fxml.Initializable;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebView;
import netscape.javascript.JSObject;
import org.w3c.dom.Element;
import org.w3c.dom.events.EventTarget;
import java.net.URL;
import java.util.*;
import java.util.function.Supplier;
public class GExtensionStoreController implements Initializable {
private GExtensionStore extensionStore = null;
private volatile boolean UIInitialized = false;
private volatile boolean initialized = false;
public BorderPane borderPane;
private WebView webView;
private LinkedList<HOverview> currentOverviews = new LinkedList<>();
private final String contentItemsContainer = "content_items_container";
@Override
public void initialize(URL location, ResourceBundle resources) {
webView = new WebView();
borderPane.setCenter(webView);
webView.getEngine().getLoadWorker().stateProperty().addListener((observableValue, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
JSObject window = (JSObject) webView.getEngine().executeScript("window");
window.setMember("app", extensionStore);
Element by_date_link = webView.getEngine().getDocument().getElementById("overview_by_date");
Element by_rating_link = webView.getEngine().getDocument().getElementById("overview_by_rating");
Element by_category_link = webView.getEngine().getDocument().getElementById("overview_by_category");
Element installed_link = webView.getEngine().getDocument().getElementById("overview_installed");
Element seach_link = webView.getEngine().getDocument().getElementById("search_page");
Map<Element, Supplier<HOverview>> hOverviewSupplier = new HashMap<>();
hOverviewSupplier.put(by_date_link, () -> new ByDateOverview(null, 0, GExtensionStore.PAGESIZE, getStoreRepository()));
hOverviewSupplier.put(by_rating_link, () -> new ByRatingOverview(null, 0, GExtensionStore.PAGESIZE, getStoreRepository()));
hOverviewSupplier.put(by_category_link, () -> new CategoryOverview(null, 0, GExtensionStore.PAGESIZE, getStoreRepository()));
hOverviewSupplier.put(installed_link, () -> new InstalledOverview(null, 0, GExtensionStore.PAGESIZE, getStoreRepository()));
hOverviewSupplier.put(seach_link, () -> new SearchOverview(null, getStoreRepository()));
Arrays.asList(by_date_link, by_rating_link, by_category_link, installed_link, seach_link).forEach(l ->
((EventTarget) l).addEventListener("click", event -> {
if (initialized) setRootOverview(hOverviewSupplier.get(l).get());
}, true));
Element first_btn = webView.getEngine().getDocument().getElementById("first_btn");
Element prev_btn = webView.getEngine().getDocument().getElementById("prev_btn");
Element next_btn = webView.getEngine().getDocument().getElementById("next_btn");
Element last_btn = webView.getEngine().getDocument().getElementById("last_btn");
Map<Element, Supplier<Integer>> newStartIndex = new HashMap<>();
newStartIndex.put(first_btn, () -> 0);
newStartIndex.put(prev_btn, () -> getCurrentOverview().getStartIndex() - GExtensionStore.PAGESIZE);
newStartIndex.put(next_btn, () -> getCurrentOverview().getStartIndex() + GExtensionStore.PAGESIZE);
newStartIndex.put(last_btn, () -> {
int lastPageSize = getCurrentOverview().getMaxAmount() % GExtensionStore.PAGESIZE;
if (lastPageSize == 0) lastPageSize = GExtensionStore.PAGESIZE;
return getCurrentOverview().getMaxAmount() - lastPageSize;
});
Arrays.asList(first_btn, prev_btn, next_btn, last_btn).forEach(l ->
((EventTarget) l).addEventListener("click", event ->{
if (!initialized || l.getAttribute("class").contains("gdisabled")) return;
overwriteCurrentOverview(getCurrentOverview().getNewPage(newStartIndex.get(l).get(), GExtensionStore.PAGESIZE));
}, true));
Element return_btn = webView.getEngine().getDocument().getElementById("return_btn");
Element generic_btn = webView.getEngine().getDocument().getElementById("generic_btn");
((EventTarget) return_btn).addEventListener("click", event -> popOverview(), true);
((EventTarget) generic_btn).addEventListener("click", event -> {
if (initialized && getCurrentOverview() != null && getCurrentOverview().buttonEnabled()) {
getCurrentOverview().buttonClick(extensionStore);
}
}, true);
UIInitialized = true;
maybeInitialized();
}
});
webView.getEngine().load(GExtensionStoreController.class.getResource("webview/index.html").toString());
}
private void setRootOverview(HOverview overview) {
currentOverviews.clear();
pushOverview(overview);
}
private void overwriteCurrentOverview(HOverview overview) {
currentOverviews.removeLast();
pushOverview(overview);
}
public void pushOverview(HOverview overview) {
currentOverviews.add(overview);
setOverview(true);
}
// private void reloadOverview(HOverview overview) {
// setOverview(true);
// }
private void popOverview() {
if (currentOverviews.size() > 1) {
currentOverviews.removeLast();
setOverview(true);
}
}
public void setOverview(boolean scrollTop) {
if (initialized) {
Platform.runLater(() -> {
HOverview overview = currentOverviews.getLast();
Element content_items_container = webView.getEngine().getDocument().getElementById(contentItemsContainer);
WebUtils.clearElement(content_items_container);
for (int i = 0; i < overview.getAmount(); i++) {
ContentItem contentItem = overview.getContentItems().get(i);
contentItem.addHtml(i, extensionStore);
}
if (scrollTop) {
webView.getEngine().executeScript("document.getElementById('" + contentItemsContainer + "').scrollTop = 0");
}
Element first_btn = webView.getEngine().getDocument().getElementById("first_btn");
Element prev_btn = webView.getEngine().getDocument().getElementById("prev_btn");
Element next_btn = webView.getEngine().getDocument().getElementById("next_btn");
Element last_btn = webView.getEngine().getDocument().getElementById("last_btn");
WebUtils.removeClass(first_btn, "gdisabled");
WebUtils.removeClass(prev_btn, "gdisabled");
WebUtils.removeClass(next_btn, "gdisabled");
WebUtils.removeClass(last_btn, "gdisabled");
boolean isLast = overview.getMaxAmount() <= overview.getAmount() + overview.getStartIndex();
boolean isFirst = overview.getStartIndex() < GExtensionStore.PAGESIZE;
if (isLast) {
WebUtils.addClass(next_btn, "gdisabled");
WebUtils.addClass(last_btn, "gdisabled");
}
if (isFirst) {
WebUtils.addClass(first_btn, "gdisabled");
WebUtils.addClass(prev_btn, "gdisabled");
}
int thispage = Math.max(1, 1 + (overview.getStartIndex() / GExtensionStore.PAGESIZE));
int lastpage = Math.max(1, 1 + ((overview.getMaxAmount() - 1) / GExtensionStore.PAGESIZE));
webView.getEngine().executeScript("document.getElementById('paging_lbl').innerHTML = '" + thispage + " / " + lastpage + "';");
Element return_btn = webView.getEngine().getDocument().getElementById("return_btn");
Element generic_btn = webView.getEngine().getDocument().getElementById("generic_btn");
WebUtils.removeClass((Element) return_btn.getParentNode(), "invisible");
WebUtils.removeClass((Element) generic_btn.getParentNode(), "invisible");
if (currentOverviews.size() < 2) WebUtils.addClass((Element) return_btn.getParentNode(), "invisible");
if (overview.buttonText() == null) WebUtils.addClass((Element) generic_btn.getParentNode(), "invisible");
else webView.getEngine().executeScript("document.getElementById('generic_btn').innerHTML = '" + overview.buttonText() + "';");
WebUtils.removeClass((Element) generic_btn.getParentNode(), "gdisabled");
if (!overview.buttonEnabled()) WebUtils.addClass((Element) generic_btn.getParentNode(), "gdisabled");
webView.getEngine().executeScript(String.format("setHeading(\"%s\", \"%s\", \"%s\")",
WebUtils.escapeHtmlNoBackslash(overview.header().iconUrl()),
WebUtils.escapeMessage(overview.header().title()),
WebUtils.escapeMessage(overview.header().description())
));
webView.getEngine().executeScript(String.format("setContentTitle(\"%s\")",
WebUtils.escapeMessage(overview.header().contentTitle())
));
});
}
}
public void maybeInitialized() {
if (UIInitialized && extensionStore != null && extensionStore.getRepository() != null) {
onFullInitialize();
}
}
private void onFullInitialize() {
initialized = true;
pushOverview(new ByDateOverview(null, 0, GExtensionStore.PAGESIZE, getStoreRepository()));
}
public void gExtensionStore(GExtensionStore gExtensionStore) {
this.extensionStore = gExtensionStore;
}
public GExtensionStore getExtensionStore() {
return extensionStore;
}
public StoreRepository getStoreRepository() {
return extensionStore.getRepository();
}
public WebView getWebView() {
return webView;
}
public HOverview getCurrentOverview() {
return currentOverviews.getLast();
}
}

View File

@ -0,0 +1,79 @@
package gearth.services.internal_extensions.extensionstore.application;
import org.w3c.dom.Element;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
public class WebUtils {
private static HashMap<String, String> entityMap = new HashMap<>();
static {
entityMap.put("&", "&amp;");
entityMap.put("<", "&lt;");
entityMap.put(">", "&gt;");
// entityMap.put("\"", "&quot;");
entityMap.put("'", "&#39;");
// entityMap.put("/", "&#x2F;");
entityMap.put("`", "&#x60;");
entityMap.put("=", "&#x3D;");
}
public static String escapeHtml(String s) {
s = escapeHtmlNoBackslash(s);
return s.replace("/", "&#x2F;");
}
public static String escapeHtmlNoBackslash(String s) {
for(String key : entityMap.keySet()) {
s = s.replace(key, entityMap.get(key));
}
return s;
}
public static String elapsedTime(int time) {
if (time < 60) return time + (time == 1 ? " second" : " seconds");
time = time/60;
if (time < 60) return time + (time == 1 ? " minute" : " minutes");
time = time/60;
if (time < 24) return time + (time == 1 ? " hour" : " hours");
int days = time/24;
if (days < 7) return days + (days == 1 ? " day" : " days");
int weeks = days/7;
if (weeks < 6) return weeks + (weeks == 1 ? " week" : " weeks");
int months = days/31;
if (months < 12) return months + (months == 1 ? " month" : " months");
int years = days/365;
return years + (years == 1 ? " year" : " years");
}
public static String escapeMessage(String text) {
text = escapeHtml(text);
return text
.replace("\n\r", "<br>")
.replace("\n", "<br>")
.replace("\r", "<br>");
}
public static void clearElement(Element node) {
while (node.hasChildNodes())
node.removeChild(node.getFirstChild());
}
public static void removeClass(Element node, String classname) {
String[] classes = node.getAttribute("class").split(" ");
List<String> classesFiltered = new ArrayList<>(Arrays.asList(classes));
classesFiltered = classesFiltered.stream().filter(s -> !s.toLowerCase().equals(classname.toLowerCase())).collect(Collectors.toList());
node.setAttribute("class", String.join(" ", classesFiltered));
}
public static void addClass(Element node, String classname) {
removeClass(node, classname);
node.setAttribute("class", node.getAttribute("class") + " " + classname);
}
}

View File

@ -0,0 +1,9 @@
package gearth.services.internal_extensions.extensionstore.application.entities;
import gearth.services.internal_extensions.extensionstore.GExtensionStore;
public interface ContentItem {
void addHtml(int i, GExtensionStore gExtensionStore);
}

View File

@ -0,0 +1,45 @@
package gearth.services.internal_extensions.extensionstore.application.entities;
import gearth.services.internal_extensions.extensionstore.GExtensionStore;
import java.util.List;
public abstract class HOverview {
protected final HOverview parent;
protected final int startIndex;
protected final int limit;
public HOverview(HOverview parent, int startIndex, int limit) {
this.parent = parent;
this.startIndex = startIndex;
this.limit = limit;
}
public interface Header {
String iconUrl();
String title();
String description();
String contentTitle();
}
public abstract String buttonText();
public abstract boolean buttonEnabled();
public int getStartIndex() {
return startIndex;
}
public int getAmount() { return getContentItems().size(); };
public abstract List<? extends ContentItem> getContentItems();
public abstract int getMaxAmount();
public abstract void buttonClick(GExtensionStore gExtensionStore);
// may be inherited from parent
public abstract Header header();
public abstract HOverview getNewPage(int startIndex, int size);
}

View File

@ -0,0 +1,19 @@
package gearth.services.internal_extensions.extensionstore.application.entities;
import gearth.services.internal_extensions.extensionstore.GExtensionStore;
import gearth.services.internal_extensions.extensionstore.repository.models.StoreExtension;
public class StoreExtensionItem implements ContentItem {
protected final StoreExtension storeExtension;
public StoreExtensionItem(StoreExtension storeExtension) {
this.storeExtension = storeExtension;
}
@Override
public void addHtml(int i, GExtensionStore gExtensionStore) {
}
}

View File

@ -0,0 +1,19 @@
package gearth.services.internal_extensions.extensionstore.application.entities.categories;
import gearth.services.internal_extensions.extensionstore.GExtensionStore;
import gearth.services.internal_extensions.extensionstore.application.entities.ContentItem;
import gearth.services.internal_extensions.extensionstore.repository.models.ExtCategory;
public class CategoryItem implements ContentItem {
private final ExtCategory category;
public CategoryItem(ExtCategory category) {
this.category = category;
}
@Override
public void addHtml(int i, GExtensionStore gExtensionStore) {
}
}

View File

@ -0,0 +1,80 @@
package gearth.services.internal_extensions.extensionstore.application.entities.categories;
import gearth.services.internal_extensions.extensionstore.GExtensionStore;
import gearth.services.internal_extensions.extensionstore.application.entities.ContentItem;
import gearth.services.internal_extensions.extensionstore.application.entities.HOverview;
import gearth.services.internal_extensions.extensionstore.repository.StoreRepository;
import gearth.services.internal_extensions.extensionstore.repository.models.ExtCategory;
import java.util.List;
import java.util.stream.Collectors;
public class CategoryOverview extends HOverview {
protected final StoreRepository storeRepository;
public CategoryOverview(HOverview parent, int startIndex, int size, StoreRepository storeRepository) {
super(parent, startIndex, size);
this.storeRepository = storeRepository;
}
@Override
public String buttonText() {
return null;
}
@Override
public boolean buttonEnabled() {
return false;
}
@Override
public List<? extends ContentItem> getContentItems() {
List<ExtCategory> categories = storeRepository.getCategories();
return categories.subList(startIndex, Math.min(startIndex + limit, categories.size())).stream()
.map(CategoryItem::new).collect(Collectors.toList());
}
@Override
public int getMaxAmount() {
return storeRepository.getCategories().size();
}
@Override
public void buttonClick(GExtensionStore gExtensionStore) {
// button is disabled
}
@Override
public Header header() {
return new Header() {
@Override
public String iconUrl() {
return "images/overviews/idea.png";
}
@Override
public String title() {
return "Categories";
}
@Override
public String description() {
return "Explore the different kinds of extensions G-Earth has to offer";
}
@Override
public String contentTitle() {
return "Categories";
}
};
}
@Override
public HOverview getNewPage(int startIndex, int size) {
return new CategoryOverview(parent, startIndex, size, storeRepository);
}
}

View File

@ -0,0 +1,19 @@
package gearth.services.internal_extensions.extensionstore.application.entities.extensiondetails;
import gearth.services.internal_extensions.extensionstore.GExtensionStore;
import gearth.services.internal_extensions.extensionstore.application.entities.ContentItem;
import gearth.services.internal_extensions.extensionstore.repository.models.StoreExtension;
public class StoreExtensionDetailsItem implements ContentItem {
private final StoreExtension storeExtension;
public StoreExtensionDetailsItem(StoreExtension storeExtension) {
this.storeExtension = storeExtension;
}
@Override
public void addHtml(int i, GExtensionStore gExtensionStore) {
}
}

View File

@ -0,0 +1,86 @@
package gearth.services.internal_extensions.extensionstore.application.entities.installed;
import gearth.services.internal_extensions.extensionstore.GExtensionStore;
import gearth.services.internal_extensions.extensionstore.application.entities.ContentItem;
import gearth.services.internal_extensions.extensionstore.application.entities.HOverview;
import gearth.services.internal_extensions.extensionstore.repository.StoreRepository;
import gearth.services.internal_extensions.extensionstore.repository.models.StoreExtension;
import gearth.services.internal_extensions.extensionstore.tools.InstalledExtension;
import gearth.services.internal_extensions.extensionstore.tools.StoreExtensionTools;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class InstalledOverview extends HOverview {
private final StoreRepository storeRepository;
public InstalledOverview(HOverview parent, int startIndex, int size, StoreRepository storeRepository) {
super(parent, startIndex, size);
this.storeRepository = storeRepository;
}
@Override
public String buttonText() {
return "Open folder";
}
@Override
public boolean buttonEnabled() {
return true;
}
@Override
public List<? extends ContentItem> getContentItems() {
List<InstalledExtension> installed = StoreExtensionTools.getInstalledExtension();
installed = installed.subList(startIndex, Math.min(startIndex + limit, installed.size()));
Map<String, StoreExtension> nameToExt = new HashMap<>();
storeRepository.getExtensions().forEach(e -> nameToExt.put(e.getTitle(), e));
return installed.stream().map(i -> new StoreExtensionInstalledItem(nameToExt.get(i.getName()), i)).collect(Collectors.toList());
}
@Override
public int getMaxAmount() {
return StoreExtensionTools.getInstalledExtension().size();
}
@Override
public void buttonClick(GExtensionStore gExtensionStore) {
// todo open installation folder
}
@Override
public Header header() {
return new Header() {
@Override
public String iconUrl() {
return "images/overviews/success.png";
}
@Override
public String title() {
return "Installed extensions";
}
@Override
public String description() {
return "Extensions that are already installed into G-Earth";
}
@Override
public String contentTitle() {
return "Installed extensions";
}
};
}
@Override
public HOverview getNewPage(int startIndex, int size) {
return new InstalledOverview(parent, startIndex, size, storeRepository);
}
}

View File

@ -0,0 +1,30 @@
package gearth.services.internal_extensions.extensionstore.application.entities.installed;
import gearth.services.internal_extensions.extensionstore.GExtensionStore;
import gearth.services.internal_extensions.extensionstore.application.entities.StoreExtensionItem;
import gearth.services.internal_extensions.extensionstore.repository.models.StoreExtension;
import gearth.services.internal_extensions.extensionstore.tools.InstalledExtension;
public class StoreExtensionInstalledItem extends StoreExtensionItem {
// color red when removed
// color orange when needs update
// otherwise normal color
private final InstalledExtension installedExtension;
public StoreExtensionInstalledItem(StoreExtension storeExtension, InstalledExtension installedExtension) {
super(storeExtension);
this.installedExtension = installedExtension;
}
@Override
public void addHtml(int i, GExtensionStore gExtensionStore) {
if (this.storeExtension != null) {
super.addHtml(i, gExtensionStore /* add custom color here */);
}
//todo
}
}

View File

@ -0,0 +1,55 @@
package gearth.services.internal_extensions.extensionstore.application.entities.queriedoverviews;
import gearth.misc.OSValidator;
import gearth.services.internal_extensions.extensionstore.application.GExtensionStoreController;
import gearth.services.internal_extensions.extensionstore.application.entities.HOverview;
import gearth.services.internal_extensions.extensionstore.repository.StoreRepository;
import gearth.services.internal_extensions.extensionstore.repository.models.StoreExtension;
import gearth.services.internal_extensions.extensionstore.repository.querying.ExtensionOrdering;
import java.util.Collections;
import java.util.List;
public class ByDateOverview extends QueriedExtensionOverview {
public ByDateOverview(HOverview parent, int startIndex, int size, StoreRepository storeRepository) {
super(parent, startIndex, size, storeRepository);
}
protected List<StoreExtension> query(int startIndex, int size) {
return storeRepository.getExtensions(startIndex, size, "", ExtensionOrdering.NEW_RELEASES,
Collections.singletonList(OSValidator.getOSFull()), null, null, null, false, false);
}
@Override
public Header header() {
return new Header() {
@Override
public String iconUrl() {
return "images/overviews/clock.png";
}
@Override
public String title() {
return "New Releases";
}
@Override
public String description() {
return "Extensions that were recently added to the G-ExtensionStore";
}
@Override
public String contentTitle() {
return "New Releases";
}
};
}
@Override
public HOverview getNewPage(int startIndex, int size) {
return new ByDateOverview(parent, startIndex, size, storeRepository);
}
}

View File

@ -0,0 +1,54 @@
package gearth.services.internal_extensions.extensionstore.application.entities.queriedoverviews;
import gearth.misc.OSValidator;
import gearth.services.internal_extensions.extensionstore.application.GExtensionStoreController;
import gearth.services.internal_extensions.extensionstore.application.entities.HOverview;
import gearth.services.internal_extensions.extensionstore.repository.StoreRepository;
import gearth.services.internal_extensions.extensionstore.repository.models.StoreExtension;
import gearth.services.internal_extensions.extensionstore.repository.querying.ExtensionOrdering;
import java.util.Collections;
import java.util.List;
public class ByRatingOverview extends QueriedExtensionOverview {
public ByRatingOverview(HOverview parent, int startIndex, int size, StoreRepository storeRepository) {
super(parent, startIndex, size, storeRepository);
}
protected List<StoreExtension> query(int startIndex, int size) {
return storeRepository.getExtensions(startIndex, size, "", ExtensionOrdering.RATING,
Collections.singletonList(OSValidator.getOSFull()), null, null, null, false, false);
}
@Override
public Header header() {
return new Header() {
@Override
public String iconUrl() {
return "images/overviews/star.png";
}
@Override
public String title() {
return "Popular Extensions";
}
@Override
public String description() {
return "Extensions sorted by rating";
}
@Override
public String contentTitle() {
return "Popular Extensions";
}
};
}
@Override
public HOverview getNewPage(int startIndex, int size) {
return new ByRatingOverview(parent, startIndex, size, storeRepository);
}
}

View File

@ -0,0 +1,4 @@
package gearth.services.internal_extensions.extensionstore.application.entities.queriedoverviews;
public class ManualQueryOverview {
}

View File

@ -0,0 +1,49 @@
package gearth.services.internal_extensions.extensionstore.application.entities.queriedoverviews;
import gearth.services.internal_extensions.extensionstore.GExtensionStore;
import gearth.services.internal_extensions.extensionstore.application.entities.ContentItem;
import gearth.services.internal_extensions.extensionstore.application.entities.HOverview;
import gearth.services.internal_extensions.extensionstore.application.entities.StoreExtensionItem;
import gearth.services.internal_extensions.extensionstore.repository.StoreRepository;
import gearth.services.internal_extensions.extensionstore.repository.models.StoreExtension;
import java.util.List;
import java.util.stream.Collectors;
public abstract class QueriedExtensionOverview extends HOverview {
protected final StoreRepository storeRepository;
public QueriedExtensionOverview(HOverview parent, int startIndex, int size, StoreRepository storeRepository) {
super(parent, startIndex, size);
this.storeRepository = storeRepository;
}
protected abstract List<StoreExtension> query(int startIndex, int size);
@Override
public String buttonText() {
return null;
}
@Override
public boolean buttonEnabled() {
return false;
}
@Override
public List<? extends ContentItem> getContentItems() {
return query(startIndex, limit).stream().map(StoreExtensionItem::new).collect(Collectors.toList());
}
@Override
public int getMaxAmount() {
return query(0, -1).size();
}
@Override
public void buttonClick(GExtensionStore gExtensionStore) {
// nothing i think
}
}

View File

@ -0,0 +1,12 @@
package gearth.services.internal_extensions.extensionstore.application.entities.search;
import gearth.services.internal_extensions.extensionstore.GExtensionStore;
import gearth.services.internal_extensions.extensionstore.application.entities.ContentItem;
public class SearchComponent implements ContentItem {
@Override
public void addHtml(int i, GExtensionStore gExtensionStore) {
}
}

View File

@ -0,0 +1,76 @@
package gearth.services.internal_extensions.extensionstore.application.entities.search;
import gearth.services.internal_extensions.extensionstore.GExtensionStore;
import gearth.services.internal_extensions.extensionstore.application.entities.ContentItem;
import gearth.services.internal_extensions.extensionstore.application.entities.HOverview;
import gearth.services.internal_extensions.extensionstore.repository.StoreRepository;
import java.util.Collections;
import java.util.List;
public class SearchOverview extends HOverview {
private final StoreRepository storeRepository;
public SearchOverview(HOverview parent, StoreRepository storeRepository) {
super(null, 0, 1);
this.storeRepository = storeRepository;
}
@Override
public String buttonText() {
return null;
}
@Override
public boolean buttonEnabled() {
return false;
}
@Override
public List<? extends ContentItem> getContentItems() {
return Collections.singletonList(new SearchComponent());
}
@Override
public int getMaxAmount() {
return 1;
}
@Override
public void buttonClick(GExtensionStore gExtensionStore) {
// nothing
}
@Override
public HOverview.Header header() {
return new Header() {
@Override
public String iconUrl() {
return "images/overviews/search.png";
}
@Override
public String title() {
return "Search";
}
@Override
public String description() {
return "Find the extension that fits your needs";
}
@Override
public String contentTitle() {
return "Search extensions";
}
};
}
@Override
public HOverview getNewPage(int startIndex, int size) {
return null; // impossible
}
}

View File

@ -38,7 +38,7 @@ public class StoreFetch {
new URL(String.format("https://raw.githubusercontent.com/%s/repo/%s/.auto-generated/extensions.json", source, version))
.openStream(), StandardCharsets.UTF_8));
storeFetchListener.success(new StoreRepository(new StoreData(config, exensions), version));
storeFetchListener.success(new StoreRepository(new StoreData(config, exensions), version, source));
} catch (Exception e) {
storeFetchListener.fail(e.getLocalizedMessage());

View File

@ -5,17 +5,20 @@ import gearth.services.internal_extensions.extensionstore.repository.querying.Ex
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StoreRepository {
public static StoreRepository EMPTY = new StoreRepository(new StoreData(new StoreConfig(new ArrayList<>(), new ArrayList<>()), new ArrayList<>()), "0.0");
public static StoreRepository EMPTY = new StoreRepository(new StoreData(new StoreConfig(new ArrayList<>(), new ArrayList<>()), new ArrayList<>()), "0.0", "sirjonasxx/G-ExtensionStore");
private final String repoVersion;
private final StoreData storeData;
private final String source;
public StoreRepository(StoreData storeData, String repoVersion) {
public StoreRepository(StoreData storeData, String repoVersion, String source) {
this.repoVersion = repoVersion;
this.storeData = storeData;
this.source = source;
}
public List<ExtCategory> getCategories() {
@ -33,11 +36,11 @@ public class StoreRepository {
public List<StoreExtension> getExtensions(int offset, int length, String queryString,
ExtensionOrdering ordering, List<String> filterOSes,
List<String> filterClients, List<String> filterFrameworks,
List<String> filterCategories, boolean inverse) {
List<String> filterCategories, boolean includeOutdated, boolean inverse) {
String queryLower = queryString.toLowerCase();
return getExtensions().stream()
Stream<StoreExtension> stream = getExtensions().stream()
.filter(ext -> ext.getTitle().toLowerCase().contains(queryLower) || ext.getDescription().toLowerCase().contains(queryLower)
|| ext.getAuthors().stream().anyMatch(author -> author.getName().toLowerCase().contains(queryLower)
|| author.getUsername() != null && author.getUsername().toLowerCase().contains(queryLower))
@ -46,10 +49,11 @@ public class StoreRepository {
|| ext.getLanguage().toLowerCase().contains(queryLower)
|| ext.getCompatibility().getSystems().stream().anyMatch(s -> s.toLowerCase().contains(queryLower))
|| ext.getCompatibility().getClients().stream().anyMatch(s -> s.toLowerCase().contains(queryLower)))
.filter(ext -> ext.getCompatibility().getSystems().stream().anyMatch(filterOSes::contains))
.filter(ext -> ext.getCompatibility().getClients().stream().anyMatch(filterClients::contains))
.filter(ext -> filterFrameworks.contains(ext.getFramework().getFramework().getName()))
.filter(ext -> ext.getCategories().stream().anyMatch(c -> filterCategories.contains(c.getName())))
.filter(ext -> filterOSes == null || ext.getCompatibility().getSystems().stream().anyMatch(filterOSes::contains))
.filter(ext -> filterClients == null || ext.getCompatibility().getClients().stream().anyMatch(filterClients::contains))
.filter(ext -> filterFrameworks == null || filterFrameworks.contains(ext.getFramework().getFramework().getName()))
.filter(ext -> filterCategories == null || ext.getCategories().stream().anyMatch(c -> filterCategories.contains(c.getName())))
.filter(ext -> includeOutdated || !ext.isOutdated())
.sorted((o1, o2) -> {
int result = 0;
if (ordering == ExtensionOrdering.RATING) result = -Integer.compare(o1.getRating(), o2.getRating());
@ -58,9 +62,12 @@ public class StoreRepository {
else if (ordering == ExtensionOrdering.ALPHABETICAL) result = o1.getTitle().toLowerCase().compareTo(o2.getTitle().toLowerCase());
return inverse ? -result : result;
})
.skip(offset)
.limit(length)
.collect(Collectors.toList());
.skip(offset);
if (length != -1) {
stream = stream.limit(length);
}
return stream.collect(Collectors.toList());
}
public List<String> getOperatingSystems() {
@ -104,6 +111,10 @@ public class StoreRepository {
public String getRepoVersion() {
return repoVersion;
}
public String getResourceUrl(String resource) {
return String.format("https://raw.githubusercontent.com/%s/repo/%s/%s", source, repoVersion, resource);
}
}

View File

@ -0,0 +1,20 @@
package gearth.services.internal_extensions.extensionstore.tools;
public class InstalledExtension {
private final String name;
private final String version;
public InstalledExtension(String name, String version) {
this.name = name;
this.version = version;
}
public String getName() {
return name;
}
public String getVersion() {
return version;
}
}

View File

@ -8,21 +8,17 @@ import gearth.services.internal_extensions.extensionstore.repository.StoreFetch;
import gearth.services.internal_extensions.extensionstore.repository.StoreRepository;
import gearth.services.internal_extensions.extensionstore.repository.models.StoreExtension;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.maven.artifact.versioning.ComparableVersion;
import org.json.JSONArray;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@ -157,6 +153,44 @@ public class StoreExtensionTools {
FileUtils.deleteDirectory(new File(extensionPath));
}
public static List<InstalledExtension> getInstalledExtension() {
List<InstalledExtension> installedExtensions = new ArrayList<>();
String path = Paths.get(NormalExtensionRunner.JARPATH, ExecutionInfo.EXTENSIONSDIRECTORY).toString();
File extensionsDir = new File(path);
File[] existingExtensions = extensionsDir.listFiles();
if (existingExtensions != null) {
for (File extension : existingExtensions) {
if (extension.isDirectory()) {
// installed through extensions store
if (extension.getName().contains("_")) {
List<String> parts = new ArrayList<>(Arrays.asList(extension.getName().split("_")));
parts.remove(parts.size() - 1);
String extensionName = String.join("_", parts);
installedExtensions.add(new InstalledExtension(extensionName, parts.get(parts.size() - 1)));
}
}
}
}
return installedExtensions;
}
// 0 = not installed
// 1 = installed
// 2 = version mismatch
public static int isExtensionInstalled(String name, String version) {
List<InstalledExtension> installedExtensions = getInstalledExtension();
if (installedExtensions.stream().anyMatch(p -> p.getName().equals(name)
&& new ComparableVersion(p.getVersion()).compareTo(new ComparableVersion(version)) >= 0))
return 1;
if (installedExtensions.stream().anyMatch(p -> p.getName().equals(name))) return 2;
return 0;
}
public static void updateExtension(String name, StoreRepository storeRepository, InstallExtListener listener) {
// remove old occurences
@ -173,7 +207,7 @@ public class StoreExtensionTools {
// installed through extensions store
if (extension.getName().contains("_")) {
List<String> parts = new ArrayList<>(Arrays.asList(extension.getName().split("_")));
parts.remove(path.length() - 1);
parts.remove(parts.size() - 1);
String extensionName = String.join("_", parts);
if (name.equals(extensionName)) {
removeExtension(extension.getPath());

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<BorderPane fx:id="borderPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gearth.services.internal_extensions.extensionstore.application.GExtensionStoreController">
</BorderPane>

View File

@ -0,0 +1,72 @@
.a_container {
margin: 0 2px 2px 2px;
background-color: #e9e9e1;
flex: 1 1 auto;
display: flex;
flex-direction: column;
padding: 8px 3px 0 3px;
}
.a_subcontainer {
flex: 1 1 auto;
display: flex;
flex-direction: column;
}
.a_lbl {
flex: 0 0 auto;
color: white;
background-color: #3179ac;
height: 13px;
max-height: 13px;
line-height: 13px;
font-size: 13px;
padding: 4px 3px;
}
.a_txt {
border: none;
margin: 0;
padding: 2px 3px;
overflow: auto;
outline: none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
resize: none;
}
.a_subject {
flex: 0 0 auto;
background-color: white;
height: 18px;
max-height: 18px;
overflow: hidden;
font-size: 15px;
line-height: 21px;
}
.a_div {
flex: 0 0 auto;
height: 6px;
max-height: 6px;
}
.a_message {
flex: 1 1 auto;
background-color: white;
}
#a_content_buttons {
flex: 0 0 38px;
margin: 13px 17px 13px 17px;
display: flex;
}

View File

@ -0,0 +1,169 @@
.forumbtn:not(.invisible) {
-webkit-user-select: none;
display: inline-flex;
border-style: solid;
height: 25px;
border-color: black;
border-width: 2px 2px 3px 2px;
border-radius: 5px;
}
.innerbtn {
flex: 0 1 auto;
width: 100%;
text-align: center;
align-items: center;
justify-content: center;
font-weight: bold;
white-space: nowrap;
font-size: 13px;
line-height: 25px;
border-style: solid;
border-width: 2px 2px 12px 2px;
border-color: red;
border-radius: 2px;
}
.forumbtn:hover:not(.gdisabled) {
cursor: pointer;
}
.forumbtn:hover:not(.gdisabled) > .innerbtn {
border-width: 0 0 12px 0;
padding-top: 2px;
}
.forumbtn:active:not(.gdisabled) {
cursor: default;
border-width: 2px;
height: 26px;
}
.forumbtn:active:not(.gdisabled) > .innerbtn {
border-width: 2px 2px 13px 2px;
padding-top: 0;
}
.forumbtn.gdisabled {
border-width: 2px;
height: 26px;
}
#paging_lbl {
font-size: 13px;
line-height: 26px;
overflow: hidden;
text-align: center;
align-items: center;
justify-content: center;
white-space: nowrap;
color: #9a9a96;
width: 50px;
}
.largebtn {
width: 98px;
min-width: 98px;
margin: 0 8px;
}
.smallbtn {
width: 21px;
min-width: 21px;
margin: 0 3px 0 2px;
}
.greybtn:not(.gdisabled) > .innerbtn {
background-color: #d1d1d1;
border-color: #bbbbbb;
}
.greybtn:hover:not(.gdisabled) > .innerbtn {
background-color: #dcdcdc;
border-color: #cacaca;
}
.greybtn:active:not(.gdisabled) > .innerbtn {
background-color: #c2c2c2;
border-color: #8c8c8c;
}
.greybtn.gdisabled > .innerbtn {
/*color: #;*/
/*background-color: #;*/
/*border-color: #;*/
}
.greybtn.gdisabled {
/*border-color: #;*/
}
.bluebtn:not(.gdisabled) > .innerbtn {
color: white;
background-color: #2792b9;
border-color: #2282a5;
}
.bluebtn:hover:not(.gdisabled) > .innerbtn {
background-color: #2999c2;
border-color: #268db3;
}
.bluebtn:active:not(.gdisabled) > .innerbtn {
background-color: #2487ac;
border-color: #18617c;
}
.bluebtn.gdisabled > .innerbtn {
color: #feffff;
background-color: #3d889d;
border-color: #3d889d;
}
.bluebtn.gdisabled {
border-color: #355b64;
}
.whitebtn:not(.gdisabled) > .innerbtn {
background-color: #f3f3f3;
border-color: #d9d9d9;
}
.whitebtn:hover:not(.gdisabled) > .innerbtn {
background-color: #ffffff;
border-color: #ebebeb;
}
.whitebtn:active:not(.gdisabled) > .innerbtn {
background-color: #e1e1e1;
border-color: #a3a3a3;
}
.whitebtn.gdisabled > .innerbtn {
color: #020202;
background-color: #c3c3c1;
border-color: #c3c3c1;
}
.whitebtn.gdisabled {
border-color: #7a7a7a;
}
.btnspacing {
flex: 1 1 auto;
}

View File

@ -0,0 +1,51 @@
.thread_item {
-webkit-user-select: none;
min-height: 41px;
display: flex;
overflow: hidden;
white-space: nowrap;
}
.thread_item > div {
border-style: solid;
border-color: #bab8b4;
border-width: 0 0 0 1px;
}
.thread_settings {
flex: 0 1 auto;
display: flex;
flex-flow: column;
width: 20px;
min-width: 20px;
}
.thread_info {
flex: 1 1 auto;
min-width: 0;
padding-left: 3px;
padding-top: 2px;
}
.thread_msgs {
flex: 0 1 auto;
width: 140px;
min-width: 140px;
padding-left: 4px;
padding-top: 2px;
}
.thread_delete_report {
flex: 0 1 auto;
width: 50px;
min-width: 50px;
display: flex;
}

View File

@ -0,0 +1,131 @@
.comment_item {
flex: 0 0 auto;
background-color: #bab8b4;
width: 100%;
display: flex;
flex-flow: column;
/*overflow: scroll;*/
}
.comment_header {
flex: 0 0 auto;
min-height: 26px;
background-color: #3179ac;
display: flex;
}
.comment_body {
display: flex;
min-height: 100px;
}
.ch_timeago {
flex: 1 1 auto;
color: white;
font-size: 13px;
margin: 7px 0 0 3px;
}
.ch_index {
flex: 0 0 auto;
color: white;
font-size: 13px;
margin: 7px 4px 0 0;
}
.ch_buttons {
flex: 0 0 auto;
display: flex;
}
.cb_author {
flex: 0 1 auto;
min-width: 130px;
max-width: 130px;
display: flex;
flex-flow: column;
overflow: hidden;
}
.cb_content {
flex: 1 1 auto;
padding: 5px 10px;
font-size: 13px;
overflow-wrap: break-word;
min-width: 0;
}
.cbc_quote {
background-color: #cccccc;
margin: 3px 10px 3px 16px;
padding: 5px;
font-size: 13px;
overflow-wrap: break-word;
min-width: 0;
}
.cba_name {
flex: 0 0 auto;
min-height: 16px;
font-size: 13px;
font-weight: bold;
margin: 8px 0 0 5px;
}
.cba_messages {
flex: 0 0 auto;
min-height: 15px;
font-size: 13px;
margin: 2px 0 0 5px;
}
.cba_look {
margin: -17px 0 0 -7px;
height: 0;
}
.comment_open > .cb_author {
background-color: #c8eff8;
}
.comment_open > .cb_content {
background-color: #ffffff;
}
.comment_unread > .cb_author {
background-color: #c8eff8;
}
.comment_unread > .cb_content {
background-color: #fef4da;
}
.comment_hidden > .cb_author {
background-color: #d7d7cf;
}
.comment_hidden > .cb_content {
background-color: #e9e9e0;
}
.comment_staffhidden > .cb_author {
background-color: #fedfd3;
}
.comment_staffhidden > .cb_content {
background-color: #fdc6bb;
}

View File

@ -0,0 +1,43 @@
#content_items_container {
flex: 1 1 auto;
background-color: #bab8b4;
border-color: white;
border-radius: 4px;
border-style: solid;
border-width: 1px;
width: 100%;
min-height: 0;
overflow-y: auto;
display: flex;
flex-flow: column;
/*overflow: scroll;*/
}
.content_item {
flex: 0 1 auto;
border-style: solid;
border-width: 1px 0 0 0;
border-color: #bab8b4;
}
.item_lightblue {
background-color: #effeff;
}
.item_darkblue {
background-color: #b5e6f9;
}
.item_grey {
background-color: #aaaaaa;
}
.item_red {
background-color: #fcb0a6;
}

View File

@ -0,0 +1,63 @@
.overview_item {
-webkit-user-select: none;
min-height: 41px;
display: flex;
overflow: hidden;
white-space: nowrap;
}
.overview_item_logo {
flex: 0 1 auto;
display: flex;
align-items: center;
justify-content: center;
width: 41px;
min-width: 41px;
}
.overview_item_info {
flex: 1 1 auto;
min-width: 0;
margin-left: 3px;
margin-top: 0;
}
.overview_item_msgs {
flex: 0 1 auto;
width: 103px;
min-width: 103px;
margin-left: 4px;
margin-top: 2px;
}
.oii_name {
font-size: 13px;
width: 100%;
overflow: hidden;
max-height: 14px;
min-height: 14px;
padding-top: 3px;
}
.oii_desc {
font-size: 11px;
margin-top: 2px;
overflow: hidden;
}
.oim_msgs {
font-size: 11px;
margin-top: 3px;
}
.oim_unread {
font-size: 11px;
margin-top: 3px;
}

View File

@ -0,0 +1,50 @@
/*@font-face {*/
/* font-family:"Ubuntu-C";*/
/* src: url("https://github.com/sirjonasxx/test/blob/main/Ubuntu-C.ttf?raw=true") format("truetype");*/
/*}*/
/*@font-face {*/
/* font-family:"Ubuntu-Habbo";*/
/* src:url("https://github.com/sirjonasxx/test/blob/main/UbuntuHabbo.woff2?raw=true") format("woff2"),*/
/* url("https://github.com/sirjonasxx/test/blob/main/UbuntuHabbo.woff?raw=true") format("woff")*/
/*}*/
/*@import url(//db.onlinewebfonts.com/c/3549b18f20fd1f535e2e9810c957c3c7?family=Ubuntu+Habbo);*/
/*@font-face {*/
/* font-family: "Ubuntu Habbo";*/
/* src: url("//db.onlinewebfonts.com/t/3549b18f20fd1f535e2e9810c957c3c7.eot");*/
/* src: url("//db.onlinewebfonts.com/t/3549b18f20fd1f535e2e9810c957c3c7.eot?#iefix") format("embedded-opentype"),*/
/* url("//db.onlinewebfonts.com/t/3549b18f20fd1f535e2e9810c957c3c7.woff2") format("woff2"),*/
/* url("//db.onlinewebfonts.com/t/3549b18f20fd1f535e2e9810c957c3c7.woff") format("woff"),*/
/* url("//db.onlinewebfonts.com/t/3549b18f20fd1f535e2e9810c957c3c7.ttf") format("truetype"),*/
/* url("//db.onlinewebfonts.com/t/3549b18f20fd1f535e2e9810c957c3c7.svg#Ubuntu Habbo") format("svg");*/
/*}*/
@font-face {
font-family:"Ubuntu Habbo";
src: url("../fonts/UbuntuHabbo.woff2") format("woff2"),
url("../fonts/UbuntuHabbo.woff") format("woff");
}
html, body, textarea {
height: 100%;
font-family: "Ubuntu Habbo", Ubuntu, sans-serif;
/*font-family: "Ubuntu-Habbo", sans-serif;*/
margin: 0;
overflow-x: hidden;
}
a, a:visited, a:hover, a:focus, a:hover, a:active { cursor: pointer; color: #3691cf; text-decoration-line: underline; text-decoration-color: #2c78aa; }
.invisible {
display: none; !important;
}
.clickable:hover:not(.gdisabled) {
cursor: pointer;
}
.clickable:active:not(.gdisabled) {
cursor: default;
}

View File

@ -0,0 +1,145 @@
.box {
display: flex;
flex-flow: column;
height: 100%;
}
.header {
height: 80px;
min-height: 80px;
width: 100%;
/*overflow: hidden;*/
border-top-width: 1px;
border-top-color: #040f18;
border-top-style: solid;
display: flex;
}
.header_logo_container {
/*float:left;*/
min-width: 80px;
background-color: black;
height: 80px;
display: inline-flex;
/*display: inline-block;*/
/*box-sizing: border-box;*/
}
.header_banner {
background-color: #153f51;
/*height: 100%;*/
/*float: right;*/
/*overflow: auto;*/
height: 80px;
display: inline-flex;
flex-grow: 100;
/*display: inline-block;*/
/*box-sizing: border-box;*/
}
#logo {
display: flex;
align-items: center;
justify-content: center;
flex-grow: 100;
}
#logo > img {
max-height: 50px;
max-width: 50px;
}
#info_title_container {
color: white;
font-weight: bold;
font-size: 25px;
margin: 10px 0 1px 0;
padding: 3px 13px 0 13px;
}
#info_desc_container {
color: white;
font-size: 13px;
padding: 1px 13px 0 13px;
overflow: hidden;
max-height: 26px;
}
.quick_links_container {
display: flex;
flex: 0 0 auto;
/*margin: 4px 5px 7px 5px;*/
margin: 6px 5px 7px 5px;
font-size: 12px;
}
.quick_links_item {
display: inline-flex;
margin-right: 8px;
white-space: nowrap;
}
.quick_links_right {
margin-left: auto;
}
.content_container {
margin: 0 2px 2px 2px;
background-color: #e9e9e1;
flex: 1 1 auto;
display: flex;
flex-flow: column;
min-height: 0;
}
#content_title {
flex: 0 1 auto;
margin: 6px 6px 4px 6px;
color: #aaaaaa;
font-weight: bold;
font-size: 17px;
/*overflow: hidden;*/
}
#content_items {
flex: 1 1 auto;
border-style: solid;
border-width: 1px 1px 2px 1px;
border-color: black;
border-radius: 6px;
padding-right: 2px;
min-height: 0;
margin: 0 3px;
display: flex;
flex-flow: column;
}
#content_buttons {
flex: 0 0 38px;
margin: 13px 2px 13px 5px;
display: flex;
}

View File

@ -0,0 +1,84 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>G-Forum</title>
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/layout.css">
<link rel="stylesheet" href="css/buttons.css">
<link rel="stylesheet" href="css/content.css">
<link rel="stylesheet" href="css/category_overview.css">
<link rel="stylesheet" href="css/extension_overview.css">
<link rel="stylesheet" href="css/comments_overview.css">
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Ubuntu:regular,bold&subset=Latin">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="js/script.js"></script>
</head>
<body>
<div class="box">
<div class="header">
<div class="header_logo_container">
<div id="logo"></div>
</div>
<div class="header_banner">
<div id="info">
<div id="info_title_container"></div>
<div id="info_desc_container"></div>
</div>
</div>
</div>
<div class="quick_links_container">
<div class="quick_links_item"><b>Quick Links:</b></div>
<div class="quick_links_item"><a id="overview_by_date">New Releases</a></div>
<div class="quick_links_item"><a id="overview_by_rating">Popular</a></div>
<div class="quick_links_item"><a id="overview_by_category">Categories</a></div>
<div class="quick_links_item"><a id="overview_installed">Installed</a></div>
<div class="quick_links_item quick_links_right"><a id="search_page">Search</a></div>
</div>
<div class="content_container">
<div id="content_title"></div>
<div id="content_items">
<div id="content_items_container">
Initializing..
</div>
</div>
<div id="content_buttons">
<div class="invisible forumbtn largebtn greybtn">
<div id="return_btn" class="innerbtn">Return</div>
</div>
<div class="btnspacing"></div>
<div class="invisible forumbtn largebtn bluebtn gdisabled">
<div id="generic_btn" class="innerbtn">Generic button</div>
</div>
<div id="first_btn" class="gdisabled forumbtn smallbtn whitebtn"><div class="innerbtn">&#60;&#60;</div></div>
<div id="prev_btn" class="gdisabled forumbtn smallbtn whitebtn"><div class="innerbtn">&#60;</div></div>
<div id="paging_lbl">1 / 1</div>
<div id="next_btn" class="gdisabled forumbtn smallbtn whitebtn"><div class="innerbtn">&#62;</div></div>
<div id="last_btn" class="gdisabled forumbtn smallbtn whitebtn"><div class="innerbtn">&#62;&#62;</div></div>
</div>
</div>
</div>
<script>
// setOverview("by_date")
</script>
</body>
</html>

View File

@ -0,0 +1,85 @@
//
// let overviewPagesInfo = {
// "by_date" : {
// "logo": "images/overviews/clock.png",
// // "logo": "https://i.imgur.com/NmWKXcH.png",
// "title": "New Releases",
// "desc": "Newly added extensions to the G-ExtensionStore"
// },
// "by_rating" : {
// "logo": "images/overviews/star.png",
// // "logo": "https://i.imgur.com/vTpk1l6.png",
// "title": "Most Popular Extensions",
// "desc": "Extensions sorted by highest ratings"
// },
// "by_category" : {
// "logo": "images/overviews/idea.png",
// // "logo": "https://i.imgur.com/ubvaGgT.png",
// "title": "Categories",
// "desc": ""
// },
// "installed" : {
// "logo": "images/overviews/success.png",
// // "logo": "https://i.imgur.com/ubvaGgT.png",
// "title": "Extensions you have already installed",
// "desc": ""
// },
// "search" : {
// "logo": "images/overviews/search.png",
// // "logo": "https://i.imgur.com/ubvaGgT.png",
// "title": "Categories",
// "desc": ""
// }
// };
//
// function setOverview(overviewName) {
// let overview = overviewPagesInfo[overviewName];
//
// $("#logo").empty();
// $('#logo').prepend(`<img src="${overview["logo"]}" />`);
//
// $("#info_title_container").html(overview["title"]);
// $("#info_desc_container").html(overview["desc"]);
//
// $("#content_title").html(overview["title"]);
// }
//
// function setCategory(badge, title, desc) {
// $("#logo").empty();
// $('#logo').prepend(`<img src="${badge}" />`);
//
// $("#info_title_container").html(title);
// $("#info_desc_container").html(desc);
//
function setHeading(badge, title, desc) {
$("#logo").empty();
$('#logo').prepend(`<img src="${badge}" />`);
$("#info_title_container").html(title);
$("#info_desc_container").html(desc);
}
function setContentTitle(text) {
$("#content_title").html(text);
}
//
// function setExtensionView(icon, title, desc) {
// $("#logo").empty();
// $('#logo').prepend(`<img src="${icon}" />`);
//
// $("#info_title_container").html(title);
// $("#info_desc_container").html(desc);
//
// $("#content_title").html(title);
// }
//
// // $(window).on('load', function () {
// // for (let overviewName in overviewPagesInfo) {
// // $(`#overview_${overviewName}`).click( function(e) {e.preventDefault(); setOverview(overviewName)});
// // }
// //
// // });