diff --git a/.gitignore b/.gitignore index 3622cd245b4976d460e4dc18c60ea895dfba32ce..7072e3190b74b3e07c5e0a8fb812a6a2e4ca8b74 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,6 @@ build/ ## iOS ios/robovm.properties + +## core +core/gen diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index e9dad69e1bf1691da140766918e6f45d47a1072a..546fe3c7f33aa503501800a5c9e88f7873344fbf 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -7,6 +7,7 @@ <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" diff --git a/android/assets/gfx/dialog_square_borderlines.9.png b/android/assets/gfx/dialog_square_borderlines.9.png new file mode 100644 index 0000000000000000000000000000000000000000..a41516c36eae47265b3a46da59cb53bd743f697d Binary files /dev/null and b/android/assets/gfx/dialog_square_borderlines.9.png differ diff --git a/android/assets/gfx/tablexiabutton_blank_blue_pressed.9.png b/android/assets/gfx/tablexiabutton_blank_blue_pressed.9.png new file mode 100644 index 0000000000000000000000000000000000000000..e543eec281f5155e2921ea83fa9f8fd6eac2449a Binary files /dev/null and b/android/assets/gfx/tablexiabutton_blank_blue_pressed.9.png differ diff --git a/android/assets/gfx/tablexiabutton_blank_blue_unpressed.9.png b/android/assets/gfx/tablexiabutton_blank_blue_unpressed.9.png new file mode 100644 index 0000000000000000000000000000000000000000..865dbe87982e2fd272faac8cdae581db4eaaac60 Binary files /dev/null and b/android/assets/gfx/tablexiabutton_blank_blue_unpressed.9.png differ diff --git a/android/assets/gfx/tablexiabutton_blank_red_pressed.9.png b/android/assets/gfx/tablexiabutton_blank_red_pressed.9.png new file mode 100644 index 0000000000000000000000000000000000000000..6157c32a6353c81701cb3da4148fde24fd8544b3 Binary files /dev/null and b/android/assets/gfx/tablexiabutton_blank_red_pressed.9.png differ diff --git a/android/assets/gfx/tablexiabutton_blank_red_unpressed.9.png b/android/assets/gfx/tablexiabutton_blank_red_unpressed.9.png new file mode 100644 index 0000000000000000000000000000000000000000..f770f4f0fde6b98d3072154e4f838a4945d9ecab Binary files /dev/null and b/android/assets/gfx/tablexiabutton_blank_red_unpressed.9.png differ diff --git a/android/assets/keystore/tablexiaTrustKeystore b/android/assets/keystore/tablexiaTrustKeystore new file mode 100644 index 0000000000000000000000000000000000000000..c6fc6aa613a00d20a189b6bfcf97cdea8c8294f3 Binary files /dev/null and b/android/assets/keystore/tablexiaTrustKeystore differ diff --git a/android/assets/text/application/application_cs.properties b/android/assets/text/application/application_cs.properties index 095741916d6899b545f9b09cd664d333bf3724e3..75e1daab1450751ff5eb2efe90f2c96351d26cac 100644 --- a/android/assets/text/application/application_cs.properties +++ b/android/assets/text/application/application_cs.properties @@ -2,6 +2,11 @@ language_system=SystĂ©movĂ˝ jazyk language_czech=ÄŚeština language_slovak=Slovenština +system_exit=Konec +system_retry=Znovu + +zipassetloader_error=Chyba: Nemohu stáhnout dodateÄŤná data! Zkontrolujte prosĂm pĹ™ipojenĂ k internetu. + mainmenu_games=Hry mainmenu_halloffame=SĂĹ slávy mainmenu_statistics=Statistiky diff --git a/android/assets/text/application/application_sk.properties b/android/assets/text/application/application_sk.properties index ed092ed093b5b0a4f3ffe2c11c2ec8ea941ad0e4..93f5351b574f18a6b2f9f2d40ed993cf75824d08 100644 --- a/android/assets/text/application/application_sk.properties +++ b/android/assets/text/application/application_sk.properties @@ -2,6 +2,11 @@ language_system=SystĂ©movĂ˝ jazyk language_czech=ÄŚeština language_slovak=SlovenÄŤina +system_exit=Koniec +system_retry=Znovu + +zipassetloader_error=Chyba: NemĂ´Ĺľem stiahnuĹĄ dodatoÄŤná dáta! Skontrolujte prosĂm pripojenie k internetu. + mainmenu_games=Hry mainmenu_halloffame=SieĹ slávy mainmenu_statistics=Ĺ tatistiky diff --git a/android/src/main/java/cz/nic/tablexia/android/AndroidLauncher.java b/android/src/main/java/cz/nic/tablexia/android/AndroidLauncher.java index 2491f3a403b8b9cc55e9fb39d5bcdacef7757543..19741ef16cc00e57c8a617c54c6fc59d5e10b5af 100644 --- a/android/src/main/java/cz/nic/tablexia/android/AndroidLauncher.java +++ b/android/src/main/java/cz/nic/tablexia/android/AndroidLauncher.java @@ -14,7 +14,6 @@ import java.io.FileOutputStream; import cz.nic.tablexia.Tablexia; import cz.nic.tablexia.debug.BuildConfig; import cz.nic.tablexia.util.Log; -import cz.nic.tablexia.util.Utility; public class AndroidLauncher extends AndroidApplication { @@ -28,9 +27,7 @@ public class AndroidLauncher extends AndroidApplication { AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); initialize(tablexia = new Tablexia(BuildConfig.BUILD_TYPE, getResources().getConfiguration().locale, - BuildConfig.VERSION_NAME, SQL_CONNECTION_TYPE, - Utility.createChecksumMapFromString(BuildConfig.ASSETS_CHECKSUMS), savedInstanceState == null), config); } diff --git a/build.gradle b/build.gradle index 549930ff26b380a9e07f65253ced24112d92e691..6281f1ab0c943aecd13059d679c3b87dc13ae3f0 100644 --- a/build.gradle +++ b/build.gradle @@ -21,9 +21,16 @@ final assetsDirName = "assets" final assetsSourceDirName = "src" final assetsDestinationDirName = "dest" +final String ASSETS_DOWNLOAD_URL = "https://www.tablexia.cz/static/assets/" + +System.setProperty("javax.net.ssl.trustStore", new File("${project(":android").projectDir.absolutePath}/assets/keystore/tablexiaTrustKeystore").getAbsolutePath()); +System.setProperty("javax.net.ssl.trustStorePassword", "tablexia"); + ext { assetsChecksumPattern = "\"=======ASSETS_CHECKSUM=======\"" assetsChecksum = [:] + + assetsPackDir = new File("${rootProject.buildDir}/${assetsDirName}/pack/") } allprojects { @@ -146,8 +153,8 @@ task zipAssets(dependsOn: [prepareSoundAssets, prepareGraphicAssets]) { if (!dir.name.equals('common')) { task("${name}_${dir.name}", type: Zip) { - archiveName = dir.getName() + ".zip" - destinationDir = new File(project(":android").projectDir.absolutePath + "/${assetsDirName}") + archiveName = dir.getName() + "_SNAPSHOT.zip" + destinationDir = rootProject.ext.assetsPackDir from "${buildDir}/${assetsDirName}/${assetsDestinationDirName}/${dir.name}" }.execute() } @@ -155,6 +162,35 @@ task zipAssets(dependsOn: [prepareSoundAssets, prepareGraphicAssets]) { } } +task processAssets(dependsOn: [':util:checksum:runChecksum', ':util:checksum:runAssetsArchivesChecksum']) { + doLast { + if (project.hasProperty('TABLEXIA_ASSETS_SERVER_USER') && project.hasProperty('TABLEXIA_ASSETS_SERVER_URL')) { + def data = new URL(ASSETS_DOWNLOAD_URL).getText() + rootProject.ext.assetsPackDir.eachFile() { file -> + String fileName = file.getName() + String[] fileNameParts = fileName.split("_SNAPSHOT\\."); + String packageName = "${fileNameParts[0]}_${assetsChecksum[fileNameParts[0]]}.${fileNameParts[1]}"; + + boolean isProductionVersion = project.hasProperty('TABLEXIA_ASSETS_UPLOAD_PRODUCTION') && Boolean.valueOf(TABLEXIA_ASSETS_UPLOAD_PRODUCTION).booleanValue() + String uploadFileName = isProductionVersion ? packageName : fileName + if (!isProductionVersion || !data.contains(packageName)) { + println "AssetsUploader: UPLOADING FILE: ${uploadFileName}" + task ("${name}_${packageName}", type:Exec) { + workingDir "${rootProject.projectDir}" + commandLine 'scp', file.getAbsolutePath(), "${TABLEXIA_ASSETS_SERVER_USER}@${TABLEXIA_ASSETS_SERVER_URL}/${uploadFileName}" + standardOutput = new ByteArrayOutputStream() + ext.output = { + return standardOutput.toString() + } + }.execute() + } else { + println "AssetsUploader: FILE: ${packageName} EXISTS ON SERVER -> SKIPPING UPLOAD" + } + } + } + } +} + def getVersionNameFromGit() { def stdout = new ByteArrayOutputStream() exec { @@ -264,7 +300,7 @@ project(":core") { apply plugin: "java" sourceSets.test.java.srcDirs = ["test/"] - tasks.processResources.dependsOn zipAssets + tasks.processResources.dependsOn processAssets dependencies { compile project(":util:checksum") diff --git a/core/build.gradle b/core/build.gradle index 03cd1bea21b97127a33a2662db7c063b93c0badd..c62a5d8b2c8fe48eea24830bbb931f986a815216 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,11 +1,44 @@ apply plugin: "java" +final String GEN_DIRECTORY = "gen/" +final String TABLEXIA_PACKAGE_PATH = "${GEN_DIRECTORY}cz/nic/tablexia/" +final String BUILD_CONFIG_FILE = "${TABLEXIA_PACKAGE_PATH}TablexiaBuildConfig.java" +final String BUILD_CONFIG_FILE_ENCODING = "UTF-8" + sourceCompatibility = 1.6 [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' -sourceSets.main.java.srcDirs = [ "src/" ] +sourceSets.main.java.srcDirs = ["src/", "gen/"] eclipse.project { name = appName + "-core" } + +clean { + delete GEN_DIRECTORY +} + +task writeTablexiaBuildConfig { + dependsOn(':util:checksum:runChecksum') + doLast { + File folder = file(TABLEXIA_PACKAGE_PATH) + if (!folder.exists()) { + folder.mkdirs() + } + File buildConfigFile = file(BUILD_CONFIG_FILE) + buildConfigFile.write("package cz.nic.tablexia;\n" + + "\n" + + "/**\n" + + " * Automatically generated file. Do not modify or add to repository!\n" + + " */\n" + + "public class TablexiaBuildConfig {\n" + + "\n" + + " public final static String VERSION_NAME = \"${tablexiaVersionName}\";\n" + + " public final static String ASSETS_CHECKSUM = \"${getMapConvertedToString(rootProject.ext.assetsChecksum)}\";\n" + + "\n" + + "}", BUILD_CONFIG_FILE_ENCODING) + } +} + +compileJava.dependsOn writeTablexiaBuildConfig diff --git a/core/src/cz/nic/tablexia/Tablexia.java b/core/src/cz/nic/tablexia/Tablexia.java index 8fce48ad91537ca48365b0f7c7d99135b1580014..7f99a093b32d73f1d6436fc850d59ec11e129ce5 100644 --- a/core/src/cz/nic/tablexia/Tablexia.java +++ b/core/src/cz/nic/tablexia/Tablexia.java @@ -3,6 +3,11 @@ package cz.nic.tablexia; import com.badlogic.gdx.Application; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.GL30; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.NinePatch; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable; import net.engio.mbassy.listener.Handler; @@ -24,15 +29,28 @@ import cz.nic.tablexia.screen.AbstractTablexiaScreen; import cz.nic.tablexia.screen.loader.LoaderScreen; import cz.nic.tablexia.util.Log; import cz.nic.tablexia.util.Utility; +import cz.nic.tablexia.util.ui.TablexiaButton; +import cz.nic.tablexia.util.ui.dialog.AbstractButtonDialog; +import cz.nic.tablexia.util.ui.dialog.text.DialogTextContent; public class Tablexia extends TablexiaApplication { + private static final String INTERNAL_GFX_ASSETS_PATH = "gfx/"; + public static final String ERROR_DIALOG_BACKGROUND_INTERNAL = INTERNAL_GFX_ASSETS_PATH + "dialog_square_borderlines.9.png"; + public static final String ERROR_BUTTON_BLUE_UNPRESSED_INTERNAL = INTERNAL_GFX_ASSETS_PATH + "tablexiabutton_blank_blue_unpressed.9.png"; + public static final String ERROR_BUTTON_BLUE_PRESSED_INTERNAL = INTERNAL_GFX_ASSETS_PATH + "tablexiabutton_blank_blue_pressed.9.png"; + public static final String ERROR_BUTTON_RED_UNPRESSED_INTERNAL = INTERNAL_GFX_ASSETS_PATH + "tablexiabutton_blank_red_unpressed.9.png"; + public static final String ERROR_BUTTON_RED_PRESSED_INTERNAL = INTERNAL_GFX_ASSETS_PATH + "tablexiabutton_blank_red_pressed.9.png"; + public static final int ERROR_DIALOG_WIDTH = 400; + public static final int ERROR_DIALOG_HEIGHT = 250; + private final SQLConnectionType sqlConnectionType; private boolean loadingComplete = false; private MainMenuContainer mainMenuContainer; private ZipAssetLoader zipAssetLoader; - private Map<String, String> buildChecksums; private boolean reset; + private boolean errorDialogShown = false; + private ScreenshotListener screenshotListener; public static class SQLConnectionType { @@ -53,12 +71,11 @@ public class Tablexia extends TablexiaApplication { } } - public Tablexia(String buildTypeKey, Locale systemLocale, String versionName, SQLConnectionType sqlConnectionType, Map<String, String> buildChecksums, boolean reset) { + public Tablexia(String buildType, Locale systemLocale, SQLConnectionType sqlConnectionType, boolean reset) { this.reset = reset; - this.buildChecksums = buildChecksums; this.sqlConnectionType = sqlConnectionType; - TablexiaSettings.init(buildTypeKey, systemLocale, versionName); + TablexiaSettings.init(buildType, systemLocale); } private void loadingComplete() { @@ -100,7 +117,7 @@ public class Tablexia extends TablexiaApplication { ApplicationTextManager.getInstance().load(locale); // async zip extraction zipAssetLoader = new ZipAssetLoader(); - zipAssetLoader.load(locale, buildChecksums); + zipAssetLoader.load(locale, Utility.createChecksumMapFromString(TablexiaBuildConfig.ASSETS_CHECKSUM)); // async external assets loading ApplicationAtlasManager.getInstance().load(); ApplicationSoundManager.getInstance().load(); @@ -182,8 +199,11 @@ public class Tablexia extends TablexiaApplication { // load internal assets if (!ApplicationFontManager.getInstance().update()) return; if (!ApplicationTextManager.getInstance().update()) return; + // load external assets if (!zipAssetLoader.update()) return; + if (processLoaderError(zipAssetLoader.getError())) return; + if (!ApplicationAtlasManager.getInstance().update()) return; if (!ApplicationSoundManager.getInstance().update()) return; @@ -192,8 +212,6 @@ public class Tablexia extends TablexiaApplication { } } - ScreenshotListener screenshotListener; - /** * Queues request for screenshot with this listener, it is called after obtaining screenshot. * @@ -237,7 +255,62 @@ public class Tablexia extends TablexiaApplication { } -//////////////////////////// APPLICATION LOADING COMPLETE EVENT +//////////////////////////// APPLICATION LOADERS + + private class LoaderErrorDialog extends AbstractButtonDialog { + + public LoaderErrorDialog(float width, float height, DialogTextContent dialogTextContent) { + super((Gdx.graphics.getWidth() / 2) - (width / 2), + (Gdx.graphics.getHeight() / 2) - (height / 2), + width, + height, + new NinePatchDrawable(new NinePatch(new Texture(Gdx.files.internal(ERROR_DIALOG_BACKGROUND_INTERNAL)))), + dialogTextContent); + + setModal(true); + + createButton(ERROR_BUTTON_BLUE_UNPRESSED_INTERNAL, + ERROR_BUTTON_BLUE_PRESSED_INTERNAL, + ApplicationTextManager.SYSTEM_RETRY, + new ClickListener() { + + @Override + public void clicked(InputEvent event, float x, float y) { + zipAssetLoader.reset(); + errorDialogShown = false; + hide(); + } + }); + + createButton(ERROR_BUTTON_RED_UNPRESSED_INTERNAL, + ERROR_BUTTON_RED_PRESSED_INTERNAL, + ApplicationTextManager.SYSTEM_EXIT, + new ClickListener() { + + @Override + public void clicked(InputEvent event, float x, float y) { + Gdx.app.exit(); + } + }); + } + + private void createButton(String unpressed, String pressed, String textKey, ClickListener clickListener) { + TablexiaButton button = new TablexiaButton(new NinePatchDrawable(new NinePatch(new Texture(Gdx.files.internal(unpressed)))), + new NinePatchDrawable(new NinePatch(new Texture(Gdx.files.internal(pressed)))), + null, + ApplicationTextManager.getInstance().getText(textKey)); + + createButton(button, clickListener); + } + } + + private boolean processLoaderError(String loaderError) { + if (loaderError != null && !errorDialogShown) { + new LoaderErrorDialog(ERROR_DIALOG_WIDTH, ERROR_DIALOG_HEIGHT, new DialogTextContent(loaderError)).show(getStage()); + errorDialogShown = true; + } + return errorDialogShown; + } public static class ApplicationLoadingCompleteEvent implements ApplicationEvent { } diff --git a/core/src/cz/nic/tablexia/TablexiaSettings.java b/core/src/cz/nic/tablexia/TablexiaSettings.java index 1fd0e5349368409fb4aed9fb1e836a2cc7175087..a1be63b1432613913216c2e5bff90767f65ca861 100644 --- a/core/src/cz/nic/tablexia/TablexiaSettings.java +++ b/core/src/cz/nic/tablexia/TablexiaSettings.java @@ -29,11 +29,12 @@ public class TablexiaSettings { private static final String PREFERENCES_KEY = "cz.nic.tablexia."; public static final String LOCALE_KEY = "locale"; - private static final String IDE_BUILD_VERSION_NAME = "DEVEL"; + private static final String IDE_BUILD_VERSION_NAME = "DEVEL"; + public static final String DEV_VERSION_TYPE = "-DEV-"; private final BuildType BUILD_TYPE; - private final String VERSION_NAME; + private final String VERSION_NAME = TablexiaBuildConfig.VERSION_NAME; private Preferences preferences; private LocaleDefinition systemLocale; @@ -140,9 +141,8 @@ public class TablexiaSettings { private static TablexiaSettings instance; - private TablexiaSettings(BuildType buildType, Locale systemLocale, String versionName) { + private TablexiaSettings(BuildType buildType, Locale systemLocale) { BUILD_TYPE = buildType; - VERSION_NAME = versionName == null ? IDE_BUILD_VERSION_NAME : versionName; this.systemLocale = LocaleDefinition.getLocaleDefinitionForLocale(systemLocale); } @@ -155,18 +155,18 @@ public class TablexiaSettings { return instance; } - static void init(String buildTypeKey, Locale systemLocale, String versionName) { - TablexiaSettings.init(BuildType.getBuildTypeForKey(buildTypeKey), systemLocale, versionName); + static void init(String buildTypeKey, Locale systemLocale) { + TablexiaSettings.init(BuildType.getBuildTypeForKey(buildTypeKey), systemLocale); } - static void init(BuildType buildType, Locale systemLocale, String versionName) { + static void init(BuildType buildType, Locale systemLocale) { if (instance != null) { String exceptionMessage = "Tablexia settings already initialized!"; Log.err(TablexiaSettings.class, exceptionMessage); throw new IllegalStateException(exceptionMessage); } - instance = new TablexiaSettings(buildType, systemLocale, versionName); + instance = new TablexiaSettings(buildType, systemLocale); } void dispose() { diff --git a/core/src/cz/nic/tablexia/loader/TablexiaAbstractFileManager.java b/core/src/cz/nic/tablexia/loader/TablexiaAbstractFileManager.java index ec8ccc68c65fcf79b85101a0eb685904d04a89d4..028d1cdbbfb1d8d960144a634a10cfd74532134c 100644 --- a/core/src/cz/nic/tablexia/loader/TablexiaAbstractFileManager.java +++ b/core/src/cz/nic/tablexia/loader/TablexiaAbstractFileManager.java @@ -115,6 +115,54 @@ public abstract class TablexiaAbstractFileManager extends AssetManager { } } + public enum DownloadStorageType implements StorageType { + + INTERNAL(RootStorageType.INTERNAL, DownloadStorageType.DOWNLOAD_DIRECTORY), + EXTERNAL(RootStorageType.EXTERNAL, DownloadStorageType.DOWNLOAD_DIRECTORY); + + public static final String DOWNLOAD_DIRECTORY = "download/"; + + private String storagePath; + private FileHandleResolver resolver; + + DownloadStorageType(RootStorageType rootStorageType, String assetsPath) { + this.storagePath = rootStorageType.getStoragePath() + assetsPath; + this.resolver = rootStorageType.getResolver(); + } + + public String getStoragePath() { + return storagePath; + } + + public FileHandleResolver getResolver() { + return resolver; + } + } + + public enum KeystoreStorageType implements StorageType { + + INTERNAL(RootStorageType.INTERNAL, KeystoreStorageType.KEYSTORE_DIRECTORY), + EXTERNAL(RootStorageType.EXTERNAL, KeystoreStorageType.KEYSTORE_DIRECTORY); + + public static final String KEYSTORE_DIRECTORY = "keystore/"; + + private String storagePath; + private FileHandleResolver resolver; + + KeystoreStorageType(RootStorageType rootStorageType, String assetsPath) { + this.storagePath = rootStorageType.getStoragePath() + assetsPath; + this.resolver = rootStorageType.getResolver(); + } + + public String getStoragePath() { + return storagePath; + } + + public FileHandleResolver getResolver() { + return resolver; + } + } + public static FileHandle getFileStoragePathFileHandle(StorageType storageType, String additionalPath) { return storageType.getResolver().resolve(storageType.getStoragePath() + additionalPath); } diff --git a/core/src/cz/nic/tablexia/loader/application/ApplicationTextManager.java b/core/src/cz/nic/tablexia/loader/application/ApplicationTextManager.java index 493054d9c7216cb6ab4d804382ee145284fd089d..c98e7c08b204f868d9251cf7b8c2a8c85ac69ef9 100644 --- a/core/src/cz/nic/tablexia/loader/application/ApplicationTextManager.java +++ b/core/src/cz/nic/tablexia/loader/application/ApplicationTextManager.java @@ -25,9 +25,14 @@ public class ApplicationTextManager extends TablexiaDataManager<I18NBundle> impl private static final String APPLICATION_TEXT_RESOURCE_FILE = "text/application/application"; - public static final String LANGUAGE_SYSTEM = "language_system"; - public static final String LANGUAGE_CZECH = "language_czech"; - public static final String LANGUAGE_SLOVAK = "language_slovak"; + public static final String SYSTEM_EXIT = "system_exit"; + public static final String SYSTEM_RETRY = "system_retry"; + + public static final String ZIPASSETLOADER_ERROR = "zipassetloader_error"; + + public static final String LANGUAGE_SYSTEM = "language_system"; + public static final String LANGUAGE_CZECH = "language_czech"; + public static final String LANGUAGE_SLOVAK = "language_slovak"; private static class ApplicationTextLoader implements AsyncTask<I18NBundle> { diff --git a/core/src/cz/nic/tablexia/loader/zip/ZipAssetLoader.java b/core/src/cz/nic/tablexia/loader/zip/ZipAssetLoader.java index 8f2b68b726b8b7ae10733791f78d6b55044c8a9f..a5468a95288b8344d217900a33fd4331f85f4754 100644 --- a/core/src/cz/nic/tablexia/loader/zip/ZipAssetLoader.java +++ b/core/src/cz/nic/tablexia/loader/zip/ZipAssetLoader.java @@ -1,5 +1,7 @@ package cz.nic.tablexia.loader.zip; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Net; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.utils.async.AsyncTask; @@ -8,6 +10,8 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.security.NoSuchAlgorithmException; import java.util.Locale; import java.util.Map; @@ -15,10 +19,13 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import cz.nic.tablexia.TablexiaSettings; +import cz.nic.tablexia.bus.ApplicationBus; import cz.nic.tablexia.checksum.Checksum; import cz.nic.tablexia.loader.IApplicationLoader; import cz.nic.tablexia.loader.TablexiaAbstractFileManager; import cz.nic.tablexia.loader.TablexiaDataManager; +import cz.nic.tablexia.loader.application.ApplicationTextManager; +import cz.nic.tablexia.screen.AbstractTablexiaScreen; import cz.nic.tablexia.util.Log; /** @@ -29,8 +36,41 @@ import cz.nic.tablexia.util.Log; */ public class ZipAssetLoader extends TablexiaDataManager<Void> implements IApplicationLoader { - public static final TablexiaAbstractFileManager.RootStorageType ZIP_FILES_STORAGE_TYPE = TablexiaAbstractFileManager.RootStorageType.INTERNAL; - public static final String ZIP_FILE_EXTENSION = ".zip"; + public static final TablexiaAbstractFileManager.StorageType ZIP_FILES_STORAGE_TYPE = TablexiaAbstractFileManager.DownloadStorageType.EXTERNAL; + public static final String ZIP_FILE_EXTENSION = ".zip"; + public static final String CHECKSUM_FILE_EXTENSION = ".checksum"; + private static final String TABLEXIA_ASSETS_DOWNLOAD_BASE_PATH = "https://www.tablexia.cz/static/assets/"; + private static final int TABLEXIA_ASSETS_DOWNLOAD_TIMEOUT = 2500; + private static final String TABLEXIA_TRUST_KEYSTORE_NAME = "tablexiaTrustKeystore"; + private static final String TABLEXIA_TRUST_KEYSTORE_PASSWORD = "tablexia"; + private static final String SNAPSHOT_PACKAGE_NAME = "SNAPSHOT"; + + public static final int DOWNLOAD_TRY_COUNT = 3; + private static final Object LOCK = new Object(); + + + private static boolean downloadResult = false; + private static boolean downloadHasResult = false; + private static Long startTime = null; + private static boolean error = false; + + private Locale locale; + private Map<String, String> buildChecksum; + + public void load(Locale locale, Map<String, String> buildChecksum) { + this.locale = locale; + this.buildChecksum = buildChecksum; + reset(); + } + + public void reset() { + error = false; + downloadResult = false; + downloadHasResult = false; + startTime = null; + + setAsyncTask(new ZipAssetLoaderTask(locale, buildChecksum)); + } private static class ZipAssetLoaderTask implements AsyncTask<Void> { @@ -42,12 +82,89 @@ public class ZipAssetLoader extends TablexiaDataManager<Void> implements IApplic this.buildChecksums = buildChecksums; } + @Override + public Void call() throws Exception { + String language = locale.getLanguage(); + String extractDestinationDirectory = TablexiaAbstractFileManager.getFileStoragePath(TablexiaAbstractFileManager.AssetsStorageType.EXTERNAL); + + if (buildChecksums != null) { + String buildChecksum = buildChecksums.get(language); + if (buildChecksum != null) { + + // check current content + Log.info(ZipAssetLoader.class, "Assets check started..."); + startTimer(); + boolean checksumResult = checkAssets((buildChecksum), extractDestinationDirectory); + resultTimer("Assets check delay"); + if (checksumResult) { + Log.info(ZipAssetLoader.class, "Assets check OK!"); + Log.info(ZipAssetLoader.class, "Continue to loading"); + return null; + } + Log.info(ZipAssetLoader.class, "Assets check FAILED!"); + + + String assetsPackageName = language + "_" + buildChecksum; + String zipAssetsPackageName = assetsPackageName + ZIP_FILE_EXTENSION; + FileHandle assetsPackageFileHandle = TablexiaAbstractFileManager.getFileStoragePathFileHandle(ZIP_FILES_STORAGE_TYPE, zipAssetsPackageName); + + // check current package file and download it if it is necessary + boolean usedSnapshot = false; + prepareKeyStore(); + if (TablexiaSettings.getInstance().getVersionName().contains(TablexiaSettings.DEV_VERSION_TYPE) || TablexiaSettings.getInstance().getBuildType() == TablexiaSettings.BuildType.DEVEL) { + Log.info(ZipAssetLoader.class, "Devel mode --> try to use SNAPSHOT assets package"); + String snapshotAssetsPackageName = language + "_" + SNAPSHOT_PACKAGE_NAME; + String snapshotZipAssetsPackageName = snapshotAssetsPackageName + ZIP_FILE_EXTENSION; + if (checkAndDownload(snapshotAssetsPackageName)) { + usedSnapshot = true; + assetsPackageFileHandle = TablexiaAbstractFileManager.getFileStoragePathFileHandle(ZIP_FILES_STORAGE_TYPE, snapshotZipAssetsPackageName); + } else { + Log.err(getClass(), String.format("Cannot download assets package: %s", snapshotZipAssetsPackageName)); + } + } + if (!usedSnapshot && !checkAndDownload(assetsPackageName)) { + error(getClass(), String.format("Cannot download assets package: %s", zipAssetsPackageName)); + return null; + } + + + // delete modified or old content + File eddFile = new File(extractDestinationDirectory); + if (eddFile.exists()) { + Log.info(ZipAssetLoader.class, "Found invalid assets content!"); + Log.info(ZipAssetLoader.class, String.format("Deleting content under: %s", extractDestinationDirectory)); + startTimer(); + deleteDirectory(eddFile); + resultTimer("Delete delay"); + } + + + // extract new content + Log.info(ZipAssetLoader.class, String.format("Extracting new content to: %s", extractDestinationDirectory)); + startTimer(); + // TODO check full disk situation + unzip(assetsPackageFileHandle, extractDestinationDirectory); + resultTimer("Extract delay"); + + } else { + error(getClass(), "BUILD CHECKSUM: no build checksum specified for language " + language); + } + } else { + error(getClass(), "BUILD CHECKSUM: no build checksum specified"); + } + + return null; + } + + +//////////////////////////// CHECK + private boolean checkAssets(String buildChecksum, String extractDestinationDirectory) { File file = new File(extractDestinationDirectory); if (file.exists() && file.isDirectory()) { try { String runtimeChecksum = Checksum.getMd5OfDir(file); - Log.debug(getClass(), "Comparing assets checksums: [BUILD: " + buildChecksum + "] - [RUNTIME: " + runtimeChecksum + "]"); + Log.debug(ZipAssetLoader.class, "Comparing assets checksums: [BUILD: " + buildChecksum + "] - [RUNTIME: " + runtimeChecksum + "]"); return runtimeChecksum.equals(buildChecksum); } catch (NoSuchAlgorithmException e) { Log.err(getClass(), "Cannot get checksum for assets!", e); @@ -58,59 +175,150 @@ public class ZipAssetLoader extends TablexiaDataManager<Void> implements IApplic return false; } - @Override - public Void call() throws Exception { - String language = locale.getLanguage(); - String extractDestinationDirectory = TablexiaAbstractFileManager.getFileStoragePath(TablexiaAbstractFileManager.AssetsStorageType.EXTERNAL); - - Long startTime = null; - if (TablexiaSettings.getInstance().isDebug()) { - startTime = System.nanoTime(); + private boolean checkAssetsPackage(FileHandle downloadedChecksum, FileHandle downloadedFile) { + if (downloadedFile.exists() && !downloadedFile.isDirectory()) { + try { + String fileChecksum = Checksum.getMd5OfFile(downloadedFile.file()); + String controlChecksum = downloadedChecksum.readString(); + Log.debug(ZipAssetLoader.class, "Comparing assets package checksum: [PACKAGE: " + fileChecksum + "] - [CONTROL: " + controlChecksum + "]"); + return fileChecksum.equals(controlChecksum); + } catch (NoSuchAlgorithmException e) { + Log.err(getClass(), "Cannot get checksum for assets package!", e); + } catch (IOException e) { + Log.err(getClass(), "Cannot get checksum for assets package!", e); + } } + return false; + } - // check current content - if (buildChecksums != null) { - String buildChecksum = buildChecksums.get(language); - if (buildChecksum != null) { - boolean checksumResult = checkAssets((buildChecksum), extractDestinationDirectory); - if (startTime != null) { - Log.debug(getClass(), String.format("Checksum delay: %05f s", (System.nanoTime() - startTime) / 1000000000.0)); - } - if (checksumResult) { - Log.info(getClass(), "Assets check OK! --> Continue to loading"); - return null; + +//////////////////////////// DOWNLOAD + + private void prepareKeyStore() { + FileHandle keystoreExternal = TablexiaAbstractFileManager.getFileStoragePathFileHandle(TablexiaAbstractFileManager.KeystoreStorageType.EXTERNAL, TABLEXIA_TRUST_KEYSTORE_NAME); + FileHandle keystoreInternal = TablexiaAbstractFileManager.getFileStoragePathFileHandle(TablexiaAbstractFileManager.KeystoreStorageType.INTERNAL, TABLEXIA_TRUST_KEYSTORE_NAME); + keystoreExternal.write(keystoreInternal.read(), false); + + System.setProperty("javax.net.ssl.trustStore", keystoreExternal.file().getAbsolutePath()); + System.setProperty("javax.net.ssl.trustStorePassword", TABLEXIA_TRUST_KEYSTORE_PASSWORD); + } + + private boolean checkAndDownload(final String fileName) { + int tryCounter = 0; + String zipFileName = fileName + ZIP_FILE_EXTENSION; + String checksumFileName = fileName + CHECKSUM_FILE_EXTENSION; + + // load checksum and package file + FileHandle zipFileHandle = TablexiaAbstractFileManager.getFileStoragePathFileHandle(TablexiaAbstractFileManager.DownloadStorageType.EXTERNAL, zipFileName); + FileHandle checksumFileHandle = TablexiaAbstractFileManager.getFileStoragePathFileHandle(TablexiaAbstractFileManager.DownloadStorageType.EXTERNAL, checksumFileName); + + while (true) { + // check if checksum and package file exists + if (checksumFileHandle.exists() && zipFileHandle.exists()) { + if (checkAssetsPackage(checksumFileHandle, zipFileHandle)) { + Log.info(ZipAssetLoader.class, String.format("Valid assets package file: %s", zipFileName)); + return true; + } else { + Log.info(ZipAssetLoader.class, String.format("Malformed assets package file: %s", zipFileName)); } } else { - Log.err(getClass(), "BUILD CHECKSUM: no build checksum specified for language " + language); + Log.info(ZipAssetLoader.class, String.format("Checksum or assets package file not found!", zipFileName)); + } + + if (tryCounter >= DOWNLOAD_TRY_COUNT) { + return false; } - } else { - Log.err(getClass(), "BUILD CHECKSUM: no build checksum specified"); - } - if (TablexiaSettings.getInstance().isDebug()) { - startTime = System.nanoTime(); + // download assets package checksum + Log.info(ZipAssetLoader.class, String.format("Downloading checksum file: %s try %d/%d", checksumFileName, tryCounter + 1, DOWNLOAD_TRY_COUNT)); + startTimer(); + downloadToOutputStream(fileName + CHECKSUM_FILE_EXTENSION, checksumFileHandle.write(false)); + resultTimer("Download delay of " + checksumFileName); + // download assets package file + Log.info(ZipAssetLoader.class, String.format("Downloading assets package file: %s try %d/%d", zipFileName, tryCounter + 1, DOWNLOAD_TRY_COUNT)); + startTimer(); + downloadToOutputStream(fileName + ZIP_FILE_EXTENSION, zipFileHandle.write(false)); + resultTimer("Download delay of " + zipFileName); + + tryCounter++; } + } + + private boolean downloadToOutputStream(final String fileName, final OutputStream os) { + downloadHasResult = false; + + Net.HttpRequest request = new Net.HttpRequest(Net.HttpMethods.GET); + request.setTimeOut(TABLEXIA_ASSETS_DOWNLOAD_TIMEOUT); + request.setUrl(TABLEXIA_ASSETS_DOWNLOAD_BASE_PATH + fileName); + + Gdx.net.sendHttpRequest(request, new Net.HttpResponseListener() { + + @Override + public void handleHttpResponse(Net.HttpResponse httpResponse) { + long length = Long.parseLong(httpResponse.getHeader("Content-Length")); + + InputStream is = httpResponse.getResultAsStream(); + + byte[] bytes = new byte[1024]; + int count = -1; + long read = 0; + try { + while ((count = is.read(bytes, 0, bytes.length)) != -1) { + os.write(bytes, 0, count); + read += count; + + final int progress = ((int) (((double) read / (double) length) * 100)); + ApplicationBus.getInstance().post(new AbstractTablexiaScreen.ScreenInfoEvent("Downloading: ", fileName + " [ " + progress + "% ]")).asynchronously(); + } + + downloadResult = true; + } catch (IOException e) { + Log.err(ZipAssetLoader.class, "Cannot download file: " + fileName + " !", e); + downloadResult = false; + } + notifyDownload(); + } + + @Override + public void failed(Throwable t) { + Log.err(ZipAssetLoader.class, "Downloading of file: " + fileName + " Failed!", t); + downloadResult = false; + notifyDownload(); + } + + @Override + public void cancelled() { + Log.info(ZipAssetLoader.class, "Downloading of file: " + fileName + " Canceled!"); + downloadResult = false; + notifyDownload(); + } + }); - // delete modified or old content - File eddFile = new File(extractDestinationDirectory); - if (eddFile.exists()) { - Log.info(getClass(), "Assets check FAILED! --> Deleting content under: " + extractDestinationDirectory); - deleteDirectory(eddFile); + // wait to download complete + synchronized (LOCK) { + if (!downloadHasResult) { + try { + LOCK.wait(); + } catch (InterruptedException e) { + Log.err(ZipAssetLoader.class, "Cannot wait to download end!", e); + } + } } - // extract new content - Log.info(getClass(), "Assets check FAILED! --> Extracting new assets to: " + extractDestinationDirectory); - String localisedZipFile = language + ZIP_FILE_EXTENSION; - unzip(ZIP_FILES_STORAGE_TYPE.getResolver().resolve(ZIP_FILES_STORAGE_TYPE.getStoragePath() + localisedZipFile), extractDestinationDirectory); + return downloadResult; + } - if (startTime != null) { - Log.debug(getClass(), String.format("Unzip delay: %05f s", (System.nanoTime() - startTime) / 1000000000.0)); + private void notifyDownload() { + synchronized (LOCK) { + downloadHasResult = true; + LOCK.notify(); } + } - return null; - } - public static void unzip(FileHandle zipFile, String extractDestinationDirectory) throws IOException { +//////////////////////////// EXTRACT + + private static void unzip(FileHandle zipFile, String extractDestinationDirectory) throws IOException { ZipInputStream zipInputStream = new ZipInputStream(new BufferedInputStream(zipFile.read())); try { ZipEntry zipEntry; @@ -145,7 +353,7 @@ public class ZipAssetLoader extends TablexiaDataManager<Void> implements IApplic } } - public static boolean deleteDirectory(File directory) { + private static boolean deleteDirectory(File directory) { if(directory.exists()) { File[] files = directory.listFiles(); @@ -162,9 +370,32 @@ public class ZipAssetLoader extends TablexiaDataManager<Void> implements IApplic return(directory.delete()); } } - - public void load(Locale locale, Map<String, String> buildChecksum) { - setAsyncTask(new ZipAssetLoaderTask(locale, buildChecksum)); - } + + +//////////////////////////// TIMER + + private static void startTimer() { + if (TablexiaSettings.getInstance().isDebug()) { + startTime = System.nanoTime(); + } + } + + private static void resultTimer(String message) { + if (startTime != null) { + Log.debug(ZipAssetLoader.class, String.format("%s: %05f s", message, (System.nanoTime() - startTime) / 1000000000.0)); + } + } + +//////////////////////////// ERROR + + private static void error(Class clazz, String message) { + Log.err(clazz, message); + ApplicationBus.getInstance().post(new AbstractTablexiaScreen.ScreenInfoEvent("Downloading: ", "ERROR")).asynchronously(); + error = true; + } + + public String getError() { + return error ? ApplicationTextManager.getInstance().getText(ApplicationTextManager.ZIPASSETLOADER_ERROR) : null; + } } \ No newline at end of file diff --git a/core/src/cz/nic/tablexia/util/ui/TablexiaButton.java b/core/src/cz/nic/tablexia/util/ui/TablexiaButton.java index 7f6fcfb83e1f692e2dfbe2e8ab35c0933aad60d2..4a45cc6574df993f19f50d2c745e04240ef68708 100644 --- a/core/src/cz/nic/tablexia/util/ui/TablexiaButton.java +++ b/core/src/cz/nic/tablexia/util/ui/TablexiaButton.java @@ -17,9 +17,9 @@ public class TablexiaButton extends TextButton { private static final String DEFAULT_BUTTON_TEXT_FONT = ApplicationFontManager.APPLICATION_DEFAULT_FONT_REGULAR; public enum ButtonType{ - BLUE(ApplicationAtlasManager.BUTTON_BLUE_PRESSED, ApplicationAtlasManager.BUTTON_BLUE_UNPRESSED), - GREEN(ApplicationAtlasManager.BUTTON_GREEN_PRESSED, ApplicationAtlasManager.BUTTON_GREEN_UNPRESSED), - RED(ApplicationAtlasManager.BUTTON_RED_PRESSED, ApplicationAtlasManager.BUTTON_RED_UNPRESSED); + BLUE (ApplicationAtlasManager.BUTTON_BLUE_PRESSED, ApplicationAtlasManager.BUTTON_BLUE_UNPRESSED), + GREEN (ApplicationAtlasManager.BUTTON_GREEN_PRESSED, ApplicationAtlasManager.BUTTON_GREEN_UNPRESSED), + RED (ApplicationAtlasManager.BUTTON_RED_PRESSED, ApplicationAtlasManager.BUTTON_RED_UNPRESSED); public static final String BUTTON_DISABLED = ApplicationAtlasManager.BUTTON_DISABLED; @@ -31,26 +31,28 @@ public class TablexiaButton extends TextButton { this.buttonUnpressedResourceName = buttonUnpressedResourceName; } - public String getButtonPressedResourceName(){ - return buttonPressedResourceName; + public NinePatch getUnpressedDrawable() { + return getNinePatchForName(buttonUnpressedResourceName); } - public String getButtonUnpressedResourceName() { - return buttonUnpressedResourceName; + public NinePatch getPressedDrawable() { + return getNinePatchForName(buttonPressedResourceName); + } + + private NinePatch getNinePatchForName(String name) { + return ApplicationAtlasManager.getInstance().getPatch(name); } } public TablexiaButton(String buttonText, ButtonType buttonType) { - super(buttonText, new TextButton.TextButtonStyle(null, null, null, ApplicationFontManager.getInstance().getFont(DEFAULT_BUTTON_TEXT_FONT))); - - NinePatch up = ApplicationAtlasManager.getInstance().getPatch(buttonType.getButtonUnpressedResourceName()); - NinePatchDrawable npdUp = new NinePatchDrawable(up); - - NinePatch down = ApplicationAtlasManager.getInstance().getPatch(buttonType.getButtonPressedResourceName()); - NinePatchDrawable npdDown = new NinePatchDrawable(down); + this(new NinePatchDrawable(buttonType.getUnpressedDrawable()), + new NinePatchDrawable(buttonType.getPressedDrawable()), + new NinePatchDrawable(ApplicationAtlasManager.getInstance().getPatch(buttonType.BUTTON_DISABLED)), + buttonText); + } - NinePatch dis = ApplicationAtlasManager.getInstance().getPatch(buttonType.BUTTON_DISABLED); - NinePatchDrawable npdDis = new NinePatchDrawable(dis); + public TablexiaButton(NinePatchDrawable npdUp, NinePatchDrawable npdDown, NinePatchDrawable npdDis, String buttonText) { + super(buttonText, new TextButton.TextButtonStyle(null, null, null, ApplicationFontManager.getInstance().getFont(DEFAULT_BUTTON_TEXT_FONT))); TextButton.TextButtonStyle textButtonStyle = new TextButton.TextButtonStyle(npdUp, npdDown, npdDis, ApplicationFontManager.getInstance().getFont(DEFAULT_BUTTON_TEXT_FONT)); textButtonStyle.fontColor = DEFAULT_BUTTON_TEXT_COLOR; diff --git a/core/src/cz/nic/tablexia/util/ui/dialog/AbstractButtonDialog.java b/core/src/cz/nic/tablexia/util/ui/dialog/AbstractButtonDialog.java index 1b9e216ed747f1db4fdfab34f73f56e3f009cf0c..56c100a96360bd389b37c2b973cfa372ca2ef362 100644 --- a/core/src/cz/nic/tablexia/util/ui/dialog/AbstractButtonDialog.java +++ b/core/src/cz/nic/tablexia/util/ui/dialog/AbstractButtonDialog.java @@ -1,6 +1,8 @@ package cz.nic.tablexia.util.ui.dialog; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable; import cz.nic.tablexia.util.ui.TablexiaButton; import cz.nic.tablexia.util.ui.dialog.text.DialogTextContent; @@ -9,17 +11,24 @@ import cz.nic.tablexia.util.ui.dialog.text.DialogTextContent; * Created by Václav TarantĂk on 9.4.15. */ public abstract class AbstractButtonDialog extends TextDialog { - private static final float BUTTON_WIDTH_RATIO_TO_DIALOG_WIDTH = 0.27f; - private static final float BUTTON_HEIGHT_RATIO = 0.5f; + + public static final float BUTTON_WIDTH_RATIO_TO_DIALOG_WIDTH = 0.27f; + public static final float BUTTON_HEIGHT_RATIO = 0.5f; public AbstractButtonDialog(float x, float y, float width, float height, BackGroundType backGroundType, DialogTextContent dialogTextContent) { super(x, y, width, height, backGroundType, dialogTextContent); } - public void createButton(String buttonText,TablexiaButton.ButtonType buttonType, ClickListener clickListener){ - if(buttonType!=null){ + public AbstractButtonDialog(float x, float y, float width, float height, NinePatchDrawable backGroundTypeDrawable, DialogTextContent dialogTextContent) { + super(x, y, width, height, backGroundTypeDrawable, dialogTextContent); + } + + public void createButton(String buttonText, TablexiaButton.ButtonType buttonType, ClickListener clickListener){ + createButton(new TablexiaButton(buttonText, buttonType), clickListener); + } - TablexiaButton textButton = new TablexiaButton(buttonText,buttonType); + public void createButton(TextButton textButton, ClickListener clickListener){ + if(textButton != null){ textButton.addListener(clickListener); diff --git a/core/src/cz/nic/tablexia/util/ui/dialog/TablexiaDialog.java b/core/src/cz/nic/tablexia/util/ui/dialog/TablexiaDialog.java index b1e667d41c159f830f475acb5802a3078d980325..227a0456c5e6936f679e147ade94e990b8b282fe 100644 --- a/core/src/cz/nic/tablexia/util/ui/dialog/TablexiaDialog.java +++ b/core/src/cz/nic/tablexia/util/ui/dialog/TablexiaDialog.java @@ -26,25 +26,37 @@ public class TablexiaDialog extends Dialog { private boolean hideOnOutsideClick = true; public enum BackGroundType { - BUBBLE_CLASSIC(ApplicationAtlasManager.DIALOG_BUBBLE_CLASSIC), - BUBBLE_ARROW_DOWN(ApplicationAtlasManager.DIALOG_BUBBLE_ARROW_DOWN), - BUBBLE_ARROW_LEFT(ApplicationAtlasManager.DIALOG_BUBBLE_ARROW_LEFT), - BUBBLE_CLASSIC_CONTINUE_BUTTON(ApplicationAtlasManager.DIALOG_BUBBLE_CLASSIC_CONTINUE_BUTTON), - DIALOG_RECTANGLE(ApplicationAtlasManager.DIALOG_RECTANGLE), - DIALOG_SQUARE(ApplicationAtlasManager.DIALOG_SQUARE), - DIALOG_SQUARE_BORDERLINES(ApplicationAtlasManager.DIALOG_SQUARE_BORDER_LINES); + BUBBLE_CLASSIC (ApplicationAtlasManager.DIALOG_BUBBLE_CLASSIC), + BUBBLE_ARROW_DOWN (ApplicationAtlasManager.DIALOG_BUBBLE_ARROW_DOWN), + BUBBLE_ARROW_LEFT (ApplicationAtlasManager.DIALOG_BUBBLE_ARROW_LEFT), + BUBBLE_CLASSIC_CONTINUE_BUTTON (ApplicationAtlasManager.DIALOG_BUBBLE_CLASSIC_CONTINUE_BUTTON), + DIALOG_RECTANGLE (ApplicationAtlasManager.DIALOG_RECTANGLE), + DIALOG_SQUARE (ApplicationAtlasManager.DIALOG_SQUARE), + DIALOG_SQUARE_BORDERLINES (ApplicationAtlasManager.DIALOG_SQUARE_BORDER_LINES); private String dialogBackgroundTextureName; BackGroundType(String dialogBackgroundTextureName) { this.dialogBackgroundTextureName = dialogBackgroundTextureName; } + + public NinePatchDrawable getDrawable() { + return new NinePatchDrawable(ApplicationAtlasManager.getInstance().getPatch(dialogBackgroundTextureName)); + } } public TablexiaDialog(float x, float y, float width, float height, BackGroundType backGroundType) { - super("", new DialogStyle(ApplicationFontManager.getInstance().getDefaultApplicationRegularFont(), - Color.BLACK, - new NinePatchDrawable(ApplicationAtlasManager.getInstance().getPatch(backGroundType.dialogBackgroundTextureName)), new SpriteDrawable(new Sprite(ApplicationAtlasManager.getInstance().getColorTexture(ApplicationAtlasManager.COLOR_OVERLAY))))); + this(x, y, width, height, backGroundType.getDrawable()); + } + + public TablexiaDialog(float x, float y, float width, float height, NinePatchDrawable backgroundTypeDrawable) { + super("", + new DialogStyle(ApplicationFontManager.getInstance().getDefaultApplicationRegularFont(), + Color.BLACK, + backgroundTypeDrawable, + new SpriteDrawable(new Sprite(ApplicationAtlasManager.getInstance().getColorTexture(ApplicationAtlasManager.COLOR_OVERLAY))))); + + //TODO MODAL DONT WORK setModal(true); setMovable(false); setResizable(false); diff --git a/core/src/cz/nic/tablexia/util/ui/dialog/TextDialog.java b/core/src/cz/nic/tablexia/util/ui/dialog/TextDialog.java index b0c1919d4494f91e3983df4f4505e06299864320..e054caefde8e48cbabaab3616d539ab043f77d73 100644 --- a/core/src/cz/nic/tablexia/util/ui/dialog/TextDialog.java +++ b/core/src/cz/nic/tablexia/util/ui/dialog/TextDialog.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.scenes.scene2d.ui.Cell; import com.badlogic.gdx.scenes.scene2d.ui.Label; +import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable; import com.badlogic.gdx.utils.Align; import cz.nic.tablexia.loader.application.ApplicationFontManager; @@ -19,7 +20,11 @@ public class TextDialog extends TablexiaDialog { private DialogTextContent dialogTextContent; public TextDialog(float x, float y, float width, float height, BackGroundType backGroundType, DialogTextContent dialogTextContent) { - super(x, y, width, height, backGroundType); + this(x, y, width, height, backGroundType.getDrawable(), dialogTextContent); + } + + public TextDialog(float x, float y, float width, float height, NinePatchDrawable backgroundTypeDrawable, DialogTextContent dialogTextContent) { + super(x, y, width, height, backgroundTypeDrawable); this.dialogTextContent = dialogTextContent; } diff --git a/desktop/build.gradle b/desktop/build.gradle index 6d9aa731a0acdeda09e416d72706c55b541f915b..1cfd2b2107bf5af32edf32313261665a7d2df641 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -48,16 +48,14 @@ task releaseJar(type: Jar) { } } -artifacts { - archives releaseJar, debugJar -} -jar.enabled = false - debugJar.dependsOn classes debugJar.dependsOn(':util:checksum:runChecksum') releaseJar.dependsOn classes releaseJar.dependsOn(':util:checksum:runChecksum') +build.dependsOn([debugJar, releaseJar]) +jar.enabled = false + eclipse { project { name = appName + "-desktop" diff --git a/desktop/src/cz/nic/tablexia/desktop/DesktopLauncher.java b/desktop/src/cz/nic/tablexia/desktop/DesktopLauncher.java index cc54dcaa48c3a9c098e7544c9bcb5579212cd8b3..3d76fb587de8c7e43bf93b02f34ca0dc4340a5b5 100644 --- a/desktop/src/cz/nic/tablexia/desktop/DesktopLauncher.java +++ b/desktop/src/cz/nic/tablexia/desktop/DesktopLauncher.java @@ -1,6 +1,5 @@ package cz.nic.tablexia.desktop; -import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Files; import com.badlogic.gdx.backends.lwjgl.LwjglApplication; import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; @@ -10,13 +9,10 @@ import java.util.Locale; import cz.nic.tablexia.Tablexia; import cz.nic.tablexia.TablexiaSettings; -import cz.nic.tablexia.util.Utility; public class DesktopLauncher { private static final String BUILD_VARIANT_MANIFEST_ATTRIBUTE = "Build-Type"; - private static final String VERSION_NAME_MANIFEST_ATTRIBUTE = "Version-Name"; - private static final String ASSETS_CHECKSUMS_MANIFEST_ATTRIBUTE = "Assets-Cheksums"; private static final String DESKTOP_ICON_PATH = "icon/"; private static final String DESKTOP_ICON_16 = DESKTOP_ICON_PATH + "desktop_icon_16.png"; @@ -33,9 +29,7 @@ public class DesktopLauncher { public static void main(String[] arg) { - String buildType = loadAttributeFromManifest(BUILD_VARIANT_MANIFEST_ATTRIBUTE); - String versionName = loadAttributeFromManifest(VERSION_NAME_MANIFEST_ATTRIBUTE); - String checksums = loadAttributeFromManifest(ASSETS_CHECKSUMS_MANIFEST_ATTRIBUTE); + String buildType = loadAttributeFromManifest(BUILD_VARIANT_MANIFEST_ATTRIBUTE, TablexiaSettings.BuildType.DEVEL.getKey()); LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); config.resizable = buildType == null || buildType.equals(TablexiaSettings.BuildType.DEVEL.getKey()); @@ -56,18 +50,13 @@ public class DesktopLauncher { config.addIcon(DESKTOP_ICON_128, Files.FileType.Internal); } - new LwjglApplication(new Tablexia(buildType, - Locale.getDefault(), - versionName, - SQL_CONNECTION_TYPE, - Utility.createChecksumMapFromString(checksums), - true), config); + new LwjglApplication(new Tablexia(buildType, Locale.getDefault(), SQL_CONNECTION_TYPE, true), config); } - private static String loadAttributeFromManifest(String attributeName) { + private static String loadAttributeFromManifest(String attributeName, String defaultValue) { if (Manifests.exists(attributeName)) { return Manifests.read(attributeName); } - return null; + return defaultValue; } } diff --git a/ios/Info.plist.xml b/ios/Info.plist.xml index 1542ac955d28c0d58b6c0986a61e16f5dbf5fcdb..fbe480ed333133bfb6797a815bda628129f43bd3 100644 --- a/ios/Info.plist.xml +++ b/ios/Info.plist.xml @@ -24,8 +24,6 @@ <string>${app.build}</string> <key>cz.nic.tablexia.BuildType</key> <string>${app.buildtype}</string> - <key>cz.nic.tablexia.AssetsChecksums</key> - <string>${app.assetschecksums}</string> <key>LSRequiresIPhoneOS</key> <true/> <key>UIViewControllerBasedStatusBarAppearance</key> diff --git a/ios/build.gradle b/ios/build.gradle index 2cd53550a48721306ff4e0061ce89acc2e11fd44..c0de588a8bd2dc89d22fa15190eb46c1d6843ff1 100644 --- a/ios/build.gradle +++ b/ios/build.gradle @@ -29,7 +29,6 @@ def updateRoboVMProperties(String buildType, String applicationId, String iconNa props.setProperty('app.version', tablexiaVersionName) props.setProperty('app.buildtype', buildType) props.setProperty('app.build', '' + tablexiaVersionCode) - props.setProperty('app.assetschecksums', getMapConvertedToString(rootProject.ext.assetsChecksum)) props.setProperty('app.executable', appName + '-' + buildType + '-' + tablexiaVersionName) props.store(propsFile.newDataOutputStream(), '') diff --git a/ios/robovm.properties b/ios/robovm.properties index fc7595766ac7bac652f90ff8af3cd0b7a1cfbb22..d70017fa371d6b595d2b26faf154c94e4061009d 100644 --- a/ios/robovm.properties +++ b/ios/robovm.properties @@ -1,6 +1,10 @@ -app.version=1.0 -app.id=cz.nic.tablexia.IOSLauncher +# +#Tue Jul 28 10:13:55 CEST 2015 +app.icon=Icon_devel +app.id=cz.nic.tablexia.devel +app.version=55b5a3f app.mainclass=cz.nic.tablexia.IOSLauncher -app.executable=IOSLauncher -app.build=1 -app.name=Tablexia-libGDX +app.executable=Tablexia-devel-55b5a3f +app.build=1438069145 +app.buildtype=devel +app.name=Tablexia diff --git a/ios/src/cz/nic/tablexia/IOSLauncher.java b/ios/src/cz/nic/tablexia/IOSLauncher.java index c13c819330875ad22bd888fd1419df9cdb7bd66a..399a4f3026a8917800e788395b102cfb6167c379 100644 --- a/ios/src/cz/nic/tablexia/IOSLauncher.java +++ b/ios/src/cz/nic/tablexia/IOSLauncher.java @@ -11,8 +11,6 @@ import org.robovm.apple.uikit.UIApplication; import java.util.Locale; -import cz.nic.tablexia.util.Utility; - public class IOSLauncher extends IOSApplication.Delegate { public static final Tablexia.SQLConnectionType SQL_CONNECTION_TYPE = new Tablexia.SQLConnectionType("SQLite.JDBCDriver", "jdbc:sqlite:"); @@ -23,14 +21,10 @@ public class IOSLauncher extends IOSApplication.Delegate { NSDictionary infoDictionary = NSBundle.getMainBundle().getInfoDictionary(); String buildType = infoDictionary.get(new NSString("cz.nic.tablexia.BuildType")).toString(); - String versionName = infoDictionary.get(new NSString("CFBundleShortVersionString")).toString(); - String checksums = infoDictionary.get(new NSString("cz.nic.tablexia.AssetsChecksums")).toString(); return new IOSApplication(new Tablexia(buildType, Locale.getDefault(), - versionName, SQL_CONNECTION_TYPE, - Utility.createChecksumMapFromString(checksums), false), config); } diff --git a/util/checksum/build.gradle b/util/checksum/build.gradle index cdb5da13ce863502356b116e8a66168ab799ca3d..a5498f48f6ffb1c428c6db00831d374b8c0a3443 100644 --- a/util/checksum/build.gradle +++ b/util/checksum/build.gradle @@ -24,3 +24,25 @@ task runChecksum(dependsOn: [classes, rootProject.tasks.prepareSoundAssets, root } } } + +task runAssetsArchivesChecksum(dependsOn: [classes, rootProject.tasks.zipAssets]) { + doLast { + rootProject.ext.assetsPackDir.eachFile() { file -> + String fileName = file.getName() + if (fileName.endsWith(".zip")) { + task ("${name}_${fileName}", type: JavaExec) { + main = MAIN_CLASS + args = [file] + classpath sourceSets.main.output.classesDir + classpath += sourceSets.main.runtimeClasspath + def stdout = new ByteArrayOutputStream() + standardOutput = stdout + + doLast { + (new File("${assetsPackDir.getAbsolutePath()}/${fileName.split("\\.")[0]}.checksum")).write(stdout.toString().trim()); + } + }.execute() + } + } + } +} \ No newline at end of file diff --git a/util/checksum/src/cz/nic/tablexia/checksum/Checksum.java b/util/checksum/src/cz/nic/tablexia/checksum/Checksum.java index 8ae5417d79d11de155a1b505784cd9d60cf1500f..8f65208a232cbaa9429740794d0f861be8738381 100644 --- a/util/checksum/src/cz/nic/tablexia/checksum/Checksum.java +++ b/util/checksum/src/cz/nic/tablexia/checksum/Checksum.java @@ -15,24 +15,24 @@ public class Checksum { System.out.println(getMd5OfDir(new File(args[0]))); } - public static String getMd5OfDir(File dir) throws NoSuchAlgorithmException, IOException { - StringBuilder checksumBuilder = new StringBuilder(); - File[] files = dir.listFiles(); - Arrays.sort(files, + public static String getMd5OfDir(File file) throws NoSuchAlgorithmException, IOException { + if (file.isDirectory()) { + StringBuilder checksumBuilder = new StringBuilder(); + File[] files = file.listFiles(); + Arrays.sort(files, new Comparator<File>() { public int compare(File a, File b) { return a.getName().compareTo(b.getName()); } }); - for (int i = 0; i < files.length; i++) { - if (files[i].isDirectory()) { + for (int i = 0; i < files.length; i++) { checksumBuilder.append(getMd5OfDir(files[i])); - } else { - checksumBuilder.append(getMd5OfFile(files[i])); } + return getMD5OfString(checksumBuilder.toString()); + } else { + return getMd5OfFile(file); } - return getMD5OfString(checksumBuilder.toString()); } public static String getMd5OfFile(File file) throws IOException, NoSuchAlgorithmException {