diff --git a/.idea/dictionaries/mac.xml b/.idea/dictionaries/mac.xml new file mode 100644 index 0000000..e6a791d --- /dev/null +++ b/.idea/dictionaries/mac.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/app-pro/build.gradle b/app-pro/build.gradle index de9601e..0a81e4c 100644 --- a/app-pro/build.gradle +++ b/app-pro/build.gradle @@ -20,15 +20,15 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 21 - buildToolsVersion '21.1.2' + compileSdkVersion 22 + buildToolsVersion '22' defaultConfig { applicationId "com.maskyn.fileeditorpro" minSdkVersion 11 - targetSdkVersion 21 - versionCode 35 - versionName "1.13.2" + targetSdkVersion 22 + versionCode 39 + versionName "1.15.1" } compileOptions { diff --git a/app-pro/manifest-merger-release-report.txt b/app-pro/manifest-merger-release-report.txt new file mode 100644 index 0000000..d568c69 --- /dev/null +++ b/app-pro/manifest-merger-release-report.txt @@ -0,0 +1,188 @@ +-- Merging decision tree log --- +manifest +ADDED from AndroidManifest.xml:20:1 + xmlns:android + ADDED from AndroidManifest.xml:20:11 + package + ADDED from AndroidManifest.xml:21:5 + INJECTED from AndroidManifest.xml:0:0 + INJECTED from AndroidManifest.xml:0:0 + android:versionName + INJECTED from AndroidManifest.xml:0:0 + INJECTED from AndroidManifest.xml:0:0 + android:versionCode + INJECTED from AndroidManifest.xml:0:0 + INJECTED from AndroidManifest.xml:0:0 + android:installLocation + ADDED from AndroidManifest.xml:22:5 +uses-permission#android.permission.WRITE_EXTERNAL_STORAGE +ADDED from AndroidManifest.xml:24:5 + android:name + ADDED from AndroidManifest.xml:24:22 +uses-permission#android.permission.ACCESS_SUPERUSER +ADDED from AndroidManifest.xml:25:5 + android:name + ADDED from AndroidManifest.xml:25:22 +supports-screens +ADDED from AndroidManifest.xml:27:5 + android:resizeable + ADDED from AndroidManifest.xml:31:9 + android:largeScreens + ADDED from AndroidManifest.xml:29:9 + android:anyDensity + ADDED from AndroidManifest.xml:28:9 + android:normalScreens + ADDED from AndroidManifest.xml:30:9 + android:xlargeScreens + ADDED from AndroidManifest.xml:33:9 + android:smallScreens + ADDED from AndroidManifest.xml:32:9 +application +ADDED from AndroidManifest.xml:35:5 +MERGED from turbo-editor.libraries:RootCommands:unspecified:11:5 +MERGED from turbo-editor.libraries:FloatingActionButton:unspecified:11:5 +MERGED from com.android.support:appcompat-v7:21.0.3:16:5 +MERGED from com.android.support:support-v4:21.0.3:16:5 +MERGED from com.github.gabrielemariotti.changeloglib:library:1.5.1:11:5 + android:supportsRtl + ADDED from AndroidManifest.xml:41:9 + android:label + ADDED from AndroidManifest.xml:38:9 + android:allowBackup + ADDED from AndroidManifest.xml:36:9 + android:icon + ADDED from AndroidManifest.xml:37:9 + android:hardwareAccelerated + ADDED from AndroidManifest.xml:39:9 + android:largeHeap + ADDED from AndroidManifest.xml:40:9 + android:name + ADDED from AndroidManifest.xml:42:9 +activity#com.maskyn.fileeditorpro.HomeActivity +ADDED from AndroidManifest.xml:47:9 + android:windowSoftInputMode + ADDED from AndroidManifest.xml:51:13 + android:configChanges + ADDED from AndroidManifest.xml:49:13 + android:theme + ADDED from AndroidManifest.xml:52:13 + android:name + ADDED from AndroidManifest.xml:48:13 + android:launchMode + ADDED from AndroidManifest.xml:50:13 +intent-filter#android.intent.action.MAIN+android.intent.category.LAUNCHER+android.intent.category.MULTIWINDOW_LAUNCHER +ADDED from AndroidManifest.xml:53:13 +action#android.intent.action.MAIN +ADDED from AndroidManifest.xml:54:17 + android:name + ADDED from AndroidManifest.xml:54:25 +category#android.intent.category.LAUNCHER +ADDED from AndroidManifest.xml:56:17 + android:name + ADDED from AndroidManifest.xml:56:27 +category#android.intent.category.MULTIWINDOW_LAUNCHER +ADDED from AndroidManifest.xml:57:17 + android:name + ADDED from AndroidManifest.xml:57:27 +intent-filter#android.intent.action.EDIT+android.intent.action.PICK+android.intent.action.VIEW+android.intent.category.BROWSABLE+android.intent.category.DEFAULT +ADDED from AndroidManifest.xml:59:13 +action#android.intent.action.VIEW +ADDED from AndroidManifest.xml:60:17 + android:name + ADDED from AndroidManifest.xml:60:25 +action#android.intent.action.EDIT +ADDED from AndroidManifest.xml:61:17 + android:name + ADDED from AndroidManifest.xml:61:25 +action#android.intent.action.PICK +ADDED from AndroidManifest.xml:62:17 + android:name + ADDED from AndroidManifest.xml:62:25 +category#android.intent.category.DEFAULT +ADDED from AndroidManifest.xml:64:17 + android:name + ADDED from AndroidManifest.xml:64:27 +category#android.intent.category.BROWSABLE +ADDED from AndroidManifest.xml:65:17 + android:name + ADDED from AndroidManifest.xml:65:27 +data +ADDED from AndroidManifest.xml:67:17 + android:scheme + ADDED from AndroidManifest.xml:67:23 +intent-filter#android.intent.action.SEND+android.intent.category.DEFAULT +ADDED from AndroidManifest.xml:76:13 +action#android.intent.action.SEND +ADDED from AndroidManifest.xml:77:17 + android:name + ADDED from AndroidManifest.xml:77:25 +activity#sharedcode.turboeditor.activity.SelectFileActivity +ADDED from AndroidManifest.xml:82:9 + android:label + ADDED from AndroidManifest.xml:85:13 + android:configChanges + ADDED from AndroidManifest.xml:84:13 + android:theme + ADDED from AndroidManifest.xml:87:13 + android:parentActivityName + ADDED from AndroidManifest.xml:86:13 + android:name + ADDED from AndroidManifest.xml:83:13 +meta-data#android.support.PARENT_ACTIVITY +ADDED from AndroidManifest.xml:88:13 + android:name + ADDED from AndroidManifest.xml:89:17 + android:value + ADDED from AndroidManifest.xml:90:17 +activity#sharedcode.turboeditor.preferences.ExtraSettingsActivity +ADDED from AndroidManifest.xml:93:9 + android:label + ADDED from AndroidManifest.xml:95:13 + android:parentActivityName + ADDED from AndroidManifest.xml:96:13 + android:name + ADDED from AndroidManifest.xml:94:13 +meta-data#com.sec.android.support.multiwindow +ADDED from AndroidManifest.xml:102:9 + android:name + ADDED from AndroidManifest.xml:103:13 + android:value + ADDED from AndroidManifest.xml:104:13 +meta-data#com.sec.android.multiwindow.DEFAULT_SIZE_W +ADDED from AndroidManifest.xml:105:9 + android:name + ADDED from AndroidManifest.xml:106:13 + android:value + ADDED from AndroidManifest.xml:107:13 +meta-data#com.sec.android.multiwindow.DEFAULT_SIZE_H +ADDED from AndroidManifest.xml:108:9 + android:name + ADDED from AndroidManifest.xml:109:13 + android:value + ADDED from AndroidManifest.xml:110:13 +meta-data#com.sec.android.multiwindow.MINIMUM_SIZE_W +ADDED from AndroidManifest.xml:111:9 + android:name + ADDED from AndroidManifest.xml:112:13 + android:value + ADDED from AndroidManifest.xml:113:13 +meta-data#com.sec.android.multiwindow.MINIMUM_SIZE_H +ADDED from AndroidManifest.xml:114:9 + android:name + ADDED from AndroidManifest.xml:115:13 + android:value + ADDED from AndroidManifest.xml:116:13 +uses-sdk +INJECTED from AndroidManifest.xml:0:0 reason: use-sdk injection requested +MERGED from turbo-editor.libraries:sharedCode:unspecified:25:5 +MERGED from turbo-editor.libraries:RootCommands:unspecified:7:5 +MERGED from turbo-editor.libraries:FloatingActionButton:unspecified:7:5 +MERGED from com.android.support:appcompat-v7:21.0.3:15:5 +MERGED from com.android.support:support-v4:21.0.3:15:5 +MERGED from com.github.gabrielemariotti.changeloglib:library:1.5.1:7:5 + android:targetSdkVersion + INJECTED from AndroidManifest.xml:0:0 + INJECTED from AndroidManifest.xml:0:0 + android:minSdkVersion + INJECTED from AndroidManifest.xml:0:0 + INJECTED from AndroidManifest.xml:0:0 diff --git a/app/build.gradle b/app/build.gradle index b67292b..1f58456 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -40,14 +40,14 @@ repositories { android { - compileSdkVersion 21 - buildToolsVersion '21.1.2' + compileSdkVersion 22 + buildToolsVersion '22' defaultConfig { applicationId "com.maskyn.fileeditor" minSdkVersion 11 - targetSdkVersion 21 - versionCode 35 - versionName "1.13.2" + targetSdkVersion 22 + versionCode 39 + versionName "1.15.1" } compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 @@ -71,7 +71,7 @@ android { dependencies { compile fileTree(dir: 'libs', include: '*.jar') compile project(':libraries:sharedCode') - compile 'com.google.android.gms:play-services:6.1.71' + compile 'com.google.android.gms:play-services-ads:6.5.+' compile('com.crashlytics.sdk.android:crashlytics:2.+@aar') { transitive = true; } diff --git a/app/manifest-merger-release-report.txt b/app/manifest-merger-release-report.txt new file mode 100644 index 0000000..d8317cf --- /dev/null +++ b/app/manifest-merger-release-report.txt @@ -0,0 +1,238 @@ +-- Merging decision tree log --- +manifest +ADDED from AndroidManifest.xml:21:1 + xmlns:android + ADDED from AndroidManifest.xml:21:11 + package + ADDED from AndroidManifest.xml:22:5 + INJECTED from AndroidManifest.xml:0:0 + INJECTED from AndroidManifest.xml:0:0 + android:versionName + INJECTED from AndroidManifest.xml:0:0 + INJECTED from AndroidManifest.xml:0:0 + android:versionCode + INJECTED from AndroidManifest.xml:0:0 + INJECTED from AndroidManifest.xml:0:0 + android:installLocation + ADDED from AndroidManifest.xml:23:5 +uses-permission#android.permission.WRITE_EXTERNAL_STORAGE +ADDED from AndroidManifest.xml:25:5 + android:name + ADDED from AndroidManifest.xml:25:22 +uses-permission#android.permission.ACCESS_SUPERUSER +ADDED from AndroidManifest.xml:26:5 + android:name + ADDED from AndroidManifest.xml:26:22 +uses-permission#android.permission.INTERNET +ADDED from AndroidManifest.xml:27:5 +MERGED from com.crashlytics.sdk.android:crashlytics:2.2.0:11:5 + android:name + ADDED from AndroidManifest.xml:27:22 +uses-permission#android.permission.ACCESS_NETWORK_STATE +ADDED from AndroidManifest.xml:28:5 + android:name + ADDED from AndroidManifest.xml:28:22 +uses-permission#com.android.vending.BILLING +ADDED from AndroidManifest.xml:29:5 + android:name + ADDED from AndroidManifest.xml:29:22 +supports-screens +ADDED from AndroidManifest.xml:31:5 + android:resizeable + ADDED from AndroidManifest.xml:35:9 + android:largeScreens + ADDED from AndroidManifest.xml:33:9 + android:anyDensity + ADDED from AndroidManifest.xml:32:9 + android:normalScreens + ADDED from AndroidManifest.xml:34:9 + android:xlargeScreens + ADDED from AndroidManifest.xml:37:9 + android:smallScreens + ADDED from AndroidManifest.xml:36:9 +application +ADDED from AndroidManifest.xml:39:5 +MERGED from turbo-editor.libraries:RootCommands:unspecified:11:5 +MERGED from turbo-editor.libraries:FloatingActionButton:unspecified:11:5 +MERGED from com.android.support:appcompat-v7:21.0.3:16:5 +MERGED from com.android.support:support-v4:21.0.3:16:5 +MERGED from com.github.gabrielemariotti.changeloglib:library:1.5.1:11:5 +MERGED from com.google.android.gms:play-services-ads:6.5.87:19:5 +MERGED from com.google.android.gms:play-services-base:6.5.87:20:5 +MERGED from com.android.support:support-v4:21.0.3:16:5 +MERGED from com.crashlytics.sdk.android:crashlytics:2.2.0:13:5 +MERGED from com.crashlytics.sdk.android:answers:1.1.0:11:5 +MERGED from io.fabric.sdk.android:fabric:1.1.0:11:5 +MERGED from com.crashlytics.sdk.android:beta:1.1.0:11:5 +MERGED from io.fabric.sdk.android:fabric:1.1.0:11:5 +MERGED from io.fabric.sdk.android:fabric:1.1.0:11:5 + android:supportsRtl + ADDED from AndroidManifest.xml:45:9 + android:label + ADDED from AndroidManifest.xml:42:9 + android:allowBackup + ADDED from AndroidManifest.xml:40:9 + android:icon + ADDED from AndroidManifest.xml:41:9 + android:hardwareAccelerated + ADDED from AndroidManifest.xml:43:9 + android:largeHeap + ADDED from AndroidManifest.xml:44:9 + android:name + ADDED from AndroidManifest.xml:46:9 +meta-data#com.google.android.gms.version +ADDED from AndroidManifest.xml:51:9 +MERGED from com.google.android.gms:play-services-base:6.5.87:21:9 + android:name + ADDED from AndroidManifest.xml:51:20 + android:value + ADDED from AndroidManifest.xml:52:13 +activity#com.maskyn.fileeditor.HomeActivity +ADDED from AndroidManifest.xml:53:9 + android:windowSoftInputMode + ADDED from AndroidManifest.xml:57:13 + android:configChanges + ADDED from AndroidManifest.xml:55:13 + android:theme + ADDED from AndroidManifest.xml:58:13 + android:name + ADDED from AndroidManifest.xml:54:13 + android:launchMode + ADDED from AndroidManifest.xml:56:13 +intent-filter#android.intent.action.MAIN+android.intent.category.LAUNCHER+android.intent.category.MULTIWINDOW_LAUNCHER +ADDED from AndroidManifest.xml:59:13 +action#android.intent.action.MAIN +ADDED from AndroidManifest.xml:60:17 + android:name + ADDED from AndroidManifest.xml:60:25 +category#android.intent.category.LAUNCHER +ADDED from AndroidManifest.xml:62:17 + android:name + ADDED from AndroidManifest.xml:62:27 +category#android.intent.category.MULTIWINDOW_LAUNCHER +ADDED from AndroidManifest.xml:63:17 + android:name + ADDED from AndroidManifest.xml:63:27 +intent-filter#android.intent.action.EDIT+android.intent.action.PICK+android.intent.action.VIEW+android.intent.category.BROWSABLE+android.intent.category.DEFAULT +ADDED from AndroidManifest.xml:65:13 +action#android.intent.action.VIEW +ADDED from AndroidManifest.xml:66:17 + android:name + ADDED from AndroidManifest.xml:66:25 +action#android.intent.action.EDIT +ADDED from AndroidManifest.xml:67:17 + android:name + ADDED from AndroidManifest.xml:67:25 +action#android.intent.action.PICK +ADDED from AndroidManifest.xml:68:17 + android:name + ADDED from AndroidManifest.xml:68:25 +category#android.intent.category.DEFAULT +ADDED from AndroidManifest.xml:70:17 + android:name + ADDED from AndroidManifest.xml:70:27 +category#android.intent.category.BROWSABLE +ADDED from AndroidManifest.xml:71:17 + android:name + ADDED from AndroidManifest.xml:71:27 +data +ADDED from AndroidManifest.xml:73:17 + android:scheme + ADDED from AndroidManifest.xml:73:23 +intent-filter#android.intent.action.SEND+android.intent.category.DEFAULT +ADDED from AndroidManifest.xml:82:13 +action#android.intent.action.SEND +ADDED from AndroidManifest.xml:83:17 + android:name + ADDED from AndroidManifest.xml:83:25 +activity#sharedcode.turboeditor.activity.SelectFileActivity +ADDED from AndroidManifest.xml:88:9 + android:label + ADDED from AndroidManifest.xml:91:13 + android:configChanges + ADDED from AndroidManifest.xml:90:13 + android:theme + ADDED from AndroidManifest.xml:93:13 + android:parentActivityName + ADDED from AndroidManifest.xml:92:13 + android:name + ADDED from AndroidManifest.xml:89:13 +meta-data#android.support.PARENT_ACTIVITY +ADDED from AndroidManifest.xml:94:9 + android:name + ADDED from AndroidManifest.xml:95:13 + android:value + ADDED from AndroidManifest.xml:96:13 +activity#sharedcode.turboeditor.preferences.ExtraSettingsActivity +ADDED from AndroidManifest.xml:99:9 + android:label + ADDED from AndroidManifest.xml:101:13 + android:parentActivityName + ADDED from AndroidManifest.xml:102:13 + android:name + ADDED from AndroidManifest.xml:100:13 +meta-data#com.sec.android.support.multiwindow +ADDED from AndroidManifest.xml:108:9 + android:name + ADDED from AndroidManifest.xml:109:13 + android:value + ADDED from AndroidManifest.xml:110:13 +meta-data#com.sec.android.multiwindow.DEFAULT_SIZE_W +ADDED from AndroidManifest.xml:111:9 + android:name + ADDED from AndroidManifest.xml:112:13 + android:value + ADDED from AndroidManifest.xml:113:13 +meta-data#com.sec.android.multiwindow.DEFAULT_SIZE_H +ADDED from AndroidManifest.xml:114:9 + android:name + ADDED from AndroidManifest.xml:115:13 + android:value + ADDED from AndroidManifest.xml:116:13 +meta-data#com.sec.android.multiwindow.MINIMUM_SIZE_W +ADDED from AndroidManifest.xml:117:9 + android:name + ADDED from AndroidManifest.xml:118:13 + android:value + ADDED from AndroidManifest.xml:119:13 +meta-data#com.sec.android.multiwindow.MINIMUM_SIZE_H +ADDED from AndroidManifest.xml:120:9 + android:name + ADDED from AndroidManifest.xml:121:13 + android:value + ADDED from AndroidManifest.xml:122:13 +activity#com.google.android.gms.ads.AdActivity +ADDED from AndroidManifest.xml:124:9 + android:configChanges + ADDED from AndroidManifest.xml:125:13 + android:name + ADDED from AndroidManifest.xml:124:19 +meta-data#com.crashlytics.ApiKey +ADDED from AndroidManifest.xml:126:9 + android:name + ADDED from AndroidManifest.xml:126:20 + android:value + ADDED from AndroidManifest.xml:126:58 +uses-sdk +INJECTED from AndroidManifest.xml:0:0 reason: use-sdk injection requested +MERGED from turbo-editor.libraries:sharedCode:unspecified:25:5 +MERGED from turbo-editor.libraries:RootCommands:unspecified:7:5 +MERGED from turbo-editor.libraries:FloatingActionButton:unspecified:7:5 +MERGED from com.android.support:appcompat-v7:21.0.3:15:5 +MERGED from com.android.support:support-v4:21.0.3:15:5 +MERGED from com.github.gabrielemariotti.changeloglib:library:1.5.1:7:5 +MERGED from com.google.android.gms:play-services-ads:6.5.87:18:5 +MERGED from com.google.android.gms:play-services-base:6.5.87:18:5 +MERGED from com.android.support:support-v4:21.0.3:15:5 +MERGED from com.crashlytics.sdk.android:crashlytics:2.2.0:7:5 +MERGED from com.crashlytics.sdk.android:answers:1.1.0:7:5 +MERGED from io.fabric.sdk.android:fabric:1.1.0:7:5 +MERGED from com.crashlytics.sdk.android:beta:1.1.0:7:5 +MERGED from io.fabric.sdk.android:fabric:1.1.0:7:5 +MERGED from io.fabric.sdk.android:fabric:1.1.0:7:5 + android:targetSdkVersion + INJECTED from AndroidManifest.xml:0:0 + INJECTED from AndroidManifest.xml:0:0 + android:minSdkVersion + INJECTED from AndroidManifest.xml:0:0 + INJECTED from AndroidManifest.xml:0:0 diff --git a/build/intermediates/dex-cache/cache.xml b/build/intermediates/dex-cache/cache.xml index bf62108..25c48a6 100644 --- a/build/intermediates/dex-cache/cache.xml +++ b/build/intermediates/dex-cache/cache.xml @@ -1,96 +1,397 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/intermediates/model_data.bin b/build/intermediates/model_data.bin index 4df665b..6036517 100644 Binary files a/build/intermediates/model_data.bin and b/build/intermediates/model_data.bin differ diff --git a/libraries/FloatingActionButton/build.gradle b/libraries/FloatingActionButton/build.gradle index 180e1a8..fe221bb 100644 --- a/libraries/FloatingActionButton/build.gradle +++ b/libraries/FloatingActionButton/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 21 - buildToolsVersion '21.1.2' + compileSdkVersion 22 + buildToolsVersion '22' defaultConfig { minSdkVersion 7 - targetSdkVersion 21 + targetSdkVersion 22 versionName "1.0" versionCode 1 } diff --git a/libraries/FloatingActionButton/build/generated/source/buildConfig/androidTest/debug/com/faizmalkani/floatingactionbutton/test/BuildConfig.java b/libraries/FloatingActionButton/build/generated/source/buildConfig/androidTest/debug/com/faizmalkani/floatingactionbutton/test/BuildConfig.java new file mode 100644 index 0000000..3fae412 --- /dev/null +++ b/libraries/FloatingActionButton/build/generated/source/buildConfig/androidTest/debug/com/faizmalkani/floatingactionbutton/test/BuildConfig.java @@ -0,0 +1,13 @@ +/** + * Automatically generated file. DO NOT MODIFY + */ +package com.faizmalkani.floatingactionbutton.test; + +public final class BuildConfig { + public static final boolean DEBUG = Boolean.parseBoolean("true"); + public static final String APPLICATION_ID = "com.faizmalkani.floatingactionbutton.test"; + public static final String BUILD_TYPE = "debug"; + public static final String FLAVOR = ""; + public static final int VERSION_CODE = 1; + public static final String VERSION_NAME = "1.0"; +} diff --git a/libraries/FloatingActionButton/build/generated/source/r/androidTest/debug/com/faizmalkani/floatingactionbutton/R.java b/libraries/FloatingActionButton/build/generated/source/r/androidTest/debug/com/faizmalkani/floatingactionbutton/R.java new file mode 100644 index 0000000..c696a42 --- /dev/null +++ b/libraries/FloatingActionButton/build/generated/source/r/androidTest/debug/com/faizmalkani/floatingactionbutton/R.java @@ -0,0 +1,27 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ +package com.faizmalkani.floatingactionbutton; + +public final class R { + public static final class attr { + public static final int colour = 0x7f010001; + public static final int drawable = 0x7f010000; + public static final int shadowColor = 0x7f010005; + public static final int shadowDx = 0x7f010003; + public static final int shadowDy = 0x7f010004; + public static final int shadowRadius = 0x7f010002; + } + public static final class styleable { + public static final int[] FloatingActionButton = { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 }; + public static final int FloatingActionButton_colour = 1; + public static final int FloatingActionButton_drawable = 0; + public static final int FloatingActionButton_shadowColor = 5; + public static final int FloatingActionButton_shadowDx = 3; + public static final int FloatingActionButton_shadowDy = 4; + public static final int FloatingActionButton_shadowRadius = 2; + } +} diff --git a/libraries/FloatingActionButton/build/generated/source/r/androidTest/debug/com/faizmalkani/floatingactionbutton/test/R.java b/libraries/FloatingActionButton/build/generated/source/r/androidTest/debug/com/faizmalkani/floatingactionbutton/test/R.java new file mode 100644 index 0000000..c2a3510 --- /dev/null +++ b/libraries/FloatingActionButton/build/generated/source/r/androidTest/debug/com/faizmalkani/floatingactionbutton/test/R.java @@ -0,0 +1,173 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package com.faizmalkani.floatingactionbutton.test; + +public final class R { + public static final class attr { + /**

Must be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int colour=0x7f010001; + /**

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int drawable=0x7f010000; + /**

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int shadowColor=0x7f010005; + /**

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int shadowDx=0x7f010003; + /**

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int shadowDy=0x7f010004; + /**

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int shadowRadius=0x7f010002; + } + public static final class styleable { + /** Attributes that can be used with a FloatingActionButton. +

Includes the following attributes:

+ + + + + + + + + + +
AttributeDescription
{@link #FloatingActionButton_colour com.faizmalkani.floatingactionbutton.test:colour}
{@link #FloatingActionButton_drawable com.faizmalkani.floatingactionbutton.test:drawable}
{@link #FloatingActionButton_shadowColor com.faizmalkani.floatingactionbutton.test:shadowColor}
{@link #FloatingActionButton_shadowDx com.faizmalkani.floatingactionbutton.test:shadowDx}
{@link #FloatingActionButton_shadowDy com.faizmalkani.floatingactionbutton.test:shadowDy}
{@link #FloatingActionButton_shadowRadius com.faizmalkani.floatingactionbutton.test:shadowRadius}
+ @see #FloatingActionButton_colour + @see #FloatingActionButton_drawable + @see #FloatingActionButton_shadowColor + @see #FloatingActionButton_shadowDx + @see #FloatingActionButton_shadowDy + @see #FloatingActionButton_shadowRadius + */ + public static final int[] FloatingActionButton = { + 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, + 0x7f010004, 0x7f010005 + }; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#colour} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton.test:colour + */ + public static final int FloatingActionButton_colour = 1; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#drawable} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton.test:drawable + */ + public static final int FloatingActionButton_drawable = 0; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#shadowColor} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton.test:shadowColor + */ + public static final int FloatingActionButton_shadowColor = 5; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#shadowDx} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton.test:shadowDx + */ + public static final int FloatingActionButton_shadowDx = 3; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#shadowDy} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton.test:shadowDy + */ + public static final int FloatingActionButton_shadowDy = 4; + /** +

This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#shadowRadius} + attribute's value can be found in the {@link #FloatingActionButton} array. + + +

Must be a floating point value, such as "1.2". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name com.faizmalkani.floatingactionbutton.test:shadowRadius + */ + public static final int FloatingActionButton_shadowRadius = 2; + }; +} diff --git a/libraries/FloatingActionButton/build/intermediates/bundles/debug/AndroidManifest.xml b/libraries/FloatingActionButton/build/intermediates/bundles/debug/AndroidManifest.xml index 28dac35..ef7ef47 100644 --- a/libraries/FloatingActionButton/build/intermediates/bundles/debug/AndroidManifest.xml +++ b/libraries/FloatingActionButton/build/intermediates/bundles/debug/AndroidManifest.xml @@ -6,7 +6,7 @@ + android:targetSdkVersion="22" /> diff --git a/libraries/FloatingActionButton/build/intermediates/bundles/debug/aapt/AndroidManifest.xml b/libraries/FloatingActionButton/build/intermediates/bundles/debug/aapt/AndroidManifest.xml new file mode 100644 index 0000000..ef7ef47 --- /dev/null +++ b/libraries/FloatingActionButton/build/intermediates/bundles/debug/aapt/AndroidManifest.xml @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/libraries/FloatingActionButton/build/intermediates/bundles/release/AndroidManifest.xml b/libraries/FloatingActionButton/build/intermediates/bundles/release/AndroidManifest.xml index 28dac35..ef7ef47 100644 --- a/libraries/FloatingActionButton/build/intermediates/bundles/release/AndroidManifest.xml +++ b/libraries/FloatingActionButton/build/intermediates/bundles/release/AndroidManifest.xml @@ -6,7 +6,7 @@ + android:targetSdkVersion="22" /> diff --git a/libraries/FloatingActionButton/build/intermediates/bundles/release/aapt/AndroidManifest.xml b/libraries/FloatingActionButton/build/intermediates/bundles/release/aapt/AndroidManifest.xml new file mode 100644 index 0000000..ef7ef47 --- /dev/null +++ b/libraries/FloatingActionButton/build/intermediates/bundles/release/aapt/AndroidManifest.xml @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/libraries/FloatingActionButton/build/intermediates/incremental/aidl/androidTest/debug/dependency.store b/libraries/FloatingActionButton/build/intermediates/incremental/aidl/androidTest/debug/dependency.store new file mode 100644 index 0000000..8b8400d Binary files /dev/null and b/libraries/FloatingActionButton/build/intermediates/incremental/aidl/androidTest/debug/dependency.store differ diff --git a/libraries/FloatingActionButton/build/intermediates/incremental/mergeAssets/androidTest/debug/merger.xml b/libraries/FloatingActionButton/build/intermediates/incremental/mergeAssets/androidTest/debug/merger.xml new file mode 100644 index 0000000..4fcf7a0 --- /dev/null +++ b/libraries/FloatingActionButton/build/intermediates/incremental/mergeAssets/androidTest/debug/merger.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/libraries/FloatingActionButton/build/intermediates/incremental/mergeResources/androidTest/debug/merger.xml b/libraries/FloatingActionButton/build/intermediates/incremental/mergeResources/androidTest/debug/merger.xml new file mode 100644 index 0000000..ed571c2 --- /dev/null +++ b/libraries/FloatingActionButton/build/intermediates/incremental/mergeResources/androidTest/debug/merger.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/libraries/FloatingActionButton/build/intermediates/manifests/androidTest/debug/AndroidManifest.xml b/libraries/FloatingActionButton/build/intermediates/manifests/androidTest/debug/AndroidManifest.xml new file mode 100644 index 0000000..700e38f --- /dev/null +++ b/libraries/FloatingActionButton/build/intermediates/manifests/androidTest/debug/AndroidManifest.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/FloatingActionButton/build/intermediates/manifests/tmp/manifestMerger1204657370108759986.xml b/libraries/FloatingActionButton/build/intermediates/manifests/tmp/manifestMerger1204657370108759986.xml new file mode 100644 index 0000000..b5967be --- /dev/null +++ b/libraries/FloatingActionButton/build/intermediates/manifests/tmp/manifestMerger1204657370108759986.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/libraries/FloatingActionButton/build/intermediates/manifests/tmp/manifestMerger5288530001266894344.xml b/libraries/FloatingActionButton/build/intermediates/manifests/tmp/manifestMerger5288530001266894344.xml new file mode 100644 index 0000000..b5967be --- /dev/null +++ b/libraries/FloatingActionButton/build/intermediates/manifests/tmp/manifestMerger5288530001266894344.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/libraries/FloatingActionButton/build/intermediates/manifests/tmp/manifestMerger7191608954865808767.xml b/libraries/FloatingActionButton/build/intermediates/manifests/tmp/manifestMerger7191608954865808767.xml new file mode 100644 index 0000000..5bae12c --- /dev/null +++ b/libraries/FloatingActionButton/build/intermediates/manifests/tmp/manifestMerger7191608954865808767.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/libraries/FloatingActionButton/build/intermediates/res/androidTest/debug/values/values.xml b/libraries/FloatingActionButton/build/intermediates/res/androidTest/debug/values/values.xml new file mode 100644 index 0000000..8a1db4a --- /dev/null +++ b/libraries/FloatingActionButton/build/intermediates/res/androidTest/debug/values/values.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/libraries/FloatingActionButton/build/intermediates/symbols/androidTest/debug/R.txt b/libraries/FloatingActionButton/build/intermediates/symbols/androidTest/debug/R.txt new file mode 100644 index 0000000..a11b389 --- /dev/null +++ b/libraries/FloatingActionButton/build/intermediates/symbols/androidTest/debug/R.txt @@ -0,0 +1,13 @@ +int attr colour 0x7f010001 +int attr drawable 0x7f010000 +int attr shadowColor 0x7f010005 +int attr shadowDx 0x7f010003 +int attr shadowDy 0x7f010004 +int attr shadowRadius 0x7f010002 +int[] styleable FloatingActionButton { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 } +int styleable FloatingActionButton_colour 1 +int styleable FloatingActionButton_drawable 0 +int styleable FloatingActionButton_shadowColor 5 +int styleable FloatingActionButton_shadowDx 3 +int styleable FloatingActionButton_shadowDy 4 +int styleable FloatingActionButton_shadowRadius 2 diff --git a/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-debug.aar b/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-debug.aar index ffcf644..394c81b 100644 Binary files a/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-debug.aar and b/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-debug.aar differ diff --git a/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-release.aar b/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-release.aar index fab2280..ef438e0 100644 Binary files a/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-release.aar and b/libraries/FloatingActionButton/build/outputs/aar/FloatingActionButton-release.aar differ diff --git a/libraries/RootCommands/build.gradle b/libraries/RootCommands/build.gradle index 9485108..44db86f 100644 --- a/libraries/RootCommands/build.gradle +++ b/libraries/RootCommands/build.gradle @@ -15,12 +15,12 @@ dependencies { } android { - compileSdkVersion 21 - buildToolsVersion '21.1.2' + compileSdkVersion 22 + buildToolsVersion '22' defaultConfig { minSdkVersion 7 - targetSdkVersion 21 + targetSdkVersion 22 } compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 diff --git a/libraries/sharedCode/build.gradle b/libraries/sharedCode/build.gradle index cfb8ba1..7982fc1 100644 --- a/libraries/sharedCode/build.gradle +++ b/libraries/sharedCode/build.gradle @@ -26,12 +26,12 @@ android { disable 'MissingTranslation', 'ExtraTranslation' } - compileSdkVersion 21 - buildToolsVersion '21.1.2' + compileSdkVersion 22 + buildToolsVersion '22' defaultConfig { minSdkVersion 11 - targetSdkVersion 21 + targetSdkVersion 22 versionCode 1 versionName "1.0" } @@ -61,9 +61,6 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':libraries:RootCommands') compile project(':libraries:FloatingActionButton') - //compile('de.greenrobot:eventbus:2.2.1') { - // exclude module: 'support-v4' - // } // compile 'com.googlecode.juniversalchardet:juniversalchardet:1.0.3' compile 'org.apache.commons:commons-lang3:3.1' compile files('libs/juniversalchardet-1.0.3.jar') diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/activity/MainActivity.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/activity/MainActivity.java index a4dbfd0..aed4331 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/activity/MainActivity.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/activity/MainActivity.java @@ -57,7 +57,6 @@ import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.EditText; @@ -74,8 +73,10 @@ import org.sufficientlysecure.rootcommands.Toolbox; import java.io.File; import java.io.UnsupportedEncodingException; +import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -87,6 +88,7 @@ import sharedcode.turboeditor.dialogfragment.FindTextDialog; import sharedcode.turboeditor.dialogfragment.NewFileDetailsDialog; import sharedcode.turboeditor.dialogfragment.NumberPickerDialog; import sharedcode.turboeditor.dialogfragment.SaveFileDialog; +import sharedcode.turboeditor.preferences.PreferenceChangeType; import sharedcode.turboeditor.preferences.PreferenceHelper; import sharedcode.turboeditor.task.SaveFileTask; import sharedcode.turboeditor.texteditor.EditTextPadding; @@ -99,7 +101,6 @@ import sharedcode.turboeditor.texteditor.SearchResult; import sharedcode.turboeditor.util.AccessStorageApi; import sharedcode.turboeditor.util.AnimationUtils; import sharedcode.turboeditor.util.AppInfoHelper; -import sharedcode.turboeditor.util.EventBusEvents; import sharedcode.turboeditor.util.IHomeActivity; import sharedcode.turboeditor.util.MimeTypes; import sharedcode.turboeditor.util.ProCheckUtils; @@ -108,29 +109,19 @@ import sharedcode.turboeditor.views.CustomDrawerLayout; import sharedcode.turboeditor.views.DialogHelper; import sharedcode.turboeditor.views.GoodScrollView; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.ENCODING; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.FONT_SIZE; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.LINE_NUMERS; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.MONOSPACE; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.READ_ONLY; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.SYNTAX; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.TEXT_SUGGESTIONS; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.THEME_CHANGE; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.WRAP_CONTENT; - public abstract class MainActivity extends ActionBarActivity implements IHomeActivity, FindTextDialog .SearchDialogInterface, GoodScrollView.ScrollInterface, PageSystem.PageSystemInterface, PageSystemButtons.PageButtonsInterface, NumberPickerDialog.INumberPickerDialog, SaveFileDialog.ISaveDialog, AdapterView.OnItemClickListener, AdapterDrawer.Callbacks{ //region VARIABLES + private static final int READ_REQUEST_CODE = 42; private static final int ID_SELECT_ALL = android.R.id.selectAll; private static final int ID_CUT = android.R.id.cut; private static final int ID_COPY = android.R.id.copy; private static final int ID_PASTE = android.R.id.paste; private static final int SELECT_FILE_CODE = 121; - private static final int KITKAT_OPEN_REQUEST_CODE = 41; private static final int SYNTAX_DELAY_MILLIS_SHORT = 250; private static final int SYNTAX_DELAY_MILLIS_LONG = 1500; private static final int ID_UNDO = R.id.im_undo; @@ -167,11 +158,10 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct private static String sFilePath = ""; private static Editor mEditor; private static HorizontalScrollView horizontalScroll; - private boolean searchingText; private static SearchResult searchResult; private static PageSystem pageSystem; private static PageSystemButtons pageSystemButtons; - private static String currentEncoding = "UTF-8"; + private static String currentEncoding = "UTF-16"; private static Toolbar toolbar; /* @@ -236,7 +226,7 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct super.onPause(); if (PreferenceHelper.getAutoSave(getBaseContext()) && mEditor.canSaveFile()) { - saveTheFile(); + saveTheFile(false); mEditor.fileSaved(); // so it doesn't ask to save in onDetach } } @@ -311,7 +301,7 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct // Set the default title getSupportActionBar().setTitle(getString(R.string.nome_app_turbo_editor)); - onEvent(new EventBusEvents.ClosedAFile()); + closedTheFile(); mDrawerLayout.openDrawer(Gravity.START); mDrawerLayout.closeDrawer(Gravity.END); @@ -335,15 +325,15 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct path = AccessStorageApi.getPath(getBaseContext(), data.getData()); } - if (requestCode == KITKAT_OPEN_REQUEST_CODE) { + if (requestCode == READ_REQUEST_CODE) { path = AccessStorageApi.getPath(getBaseContext(), data.getData()); } if (!TextUtils.isEmpty(path)) { File file = new File(path); if (file.isFile() && file.exists()) { - onEvent(new EventBusEvents.NewFileToOpen(new File - (path))); + newFileToOpen(new File + (path), ""); } } @@ -355,7 +345,7 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct // Path of the file selected String filePath = files.get(position).getAbsolutePath(); // Send the event that a file was selected - onEvent(new EventBusEvents.NewFileToOpen(new File(filePath))); + newFileToOpen(new File(filePath), ""); } //endregion @@ -364,7 +354,7 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct @Override public boolean onCreateOptionsMenu(Menu menu) { - if (fileOpened && searchingText) + if (fileOpened && searchResult != null) getMenuInflater().inflate(R.menu.fragment_editor_search, menu); else if (fileOpened) getMenuInflater().inflate(R.menu.fragment_editor, menu); @@ -374,14 +364,18 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct @Override public boolean onPrepareOptionsMenu(Menu menu) { - if (fileOpened && searchingText) { + if (fileOpened && searchResult != null) { MenuItem imReplace = menu.findItem(R.id.im_replace); + MenuItem imReplaceAll = menu.findItem(R.id.im_replace_all); MenuItem imPrev = menu.findItem(R.id.im_previous_item); MenuItem imNext = menu.findItem(R.id.im_next_item); if (imReplace != null) imReplace.setVisible(searchResult.canReplaceSomething()); + if (imReplaceAll != null) + imReplaceAll.setVisible(searchResult.canReplaceSomething()); + if (imPrev != null) imPrev.setVisible(searchResult.hasPrevious()); @@ -432,8 +426,11 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct Toast.makeText(getBaseContext(), "drawer click", Toast.LENGTH_SHORT).show(); mDrawerLayout.closeDrawer(Gravity.END); return true; - } else if (i == R.id.im_save) { - saveTheFile(); + } else if (i == R.id.im_save_normaly) { + saveTheFile(false); + + } else if (i == R.id.im_save_as) { + saveTheFile(true); } else if (i == R.id.im_undo) { mEditor.onTextContextMenuItem(ID_UNDO); @@ -445,11 +442,14 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct FindTextDialog.newInstance(mEditor.getText().toString()).show(getFragmentManager() .beginTransaction(), "dialog"); } else if (i == R.id.im_cancel) { - searchingText = false; + searchResult = null; invalidateOptionsMenu(); } else if (i == R.id.im_replace) { - replaceText(); + replaceText(false); + + } else if (i == R.id.im_replace_all) { + replaceText(true); } else if (i == R.id.im_next_item) { nextResult(); @@ -475,27 +475,30 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct } else if (i == R.id.im_info) { FileInfoDialog.newInstance(sFilePath).show(getFragmentManager().beginTransaction(), "dialog"); } - - else if (i == R.id.im_donate) { - DialogHelper.showDonateDialog(this); - } return super.onOptionsItemSelected(item); } //endregion // region OTHER THINGS - void replaceText() { - int start = searchResult.foundIndex.get(searchResult.index); - int end = start + searchResult.textLength; - mEditor.setText(mEditor.getText().replace(start, end, searchResult.textToReplace)); - searchResult.doneReplace(); + void replaceText(boolean all) { + if (all) { + mEditor.setText(mEditor.getText().toString().replaceAll(searchResult.whatToSearch, searchResult.textToReplace)); - invalidateOptionsMenu(); + searchResult = null; + invalidateOptionsMenu(); + } else { + int start = searchResult.foundIndex.get(searchResult.index); + int end = start + searchResult.textLength; + mEditor.setText(mEditor.getText().replace(start, end, searchResult.textToReplace)); + searchResult.doneReplace(); - if (searchResult.hasNext()) - nextResult(); - else if (searchResult.hasPrevious()) - previousResult(); + invalidateOptionsMenu(); + + if (searchResult.hasNext()) + nextResult(); + else if (searchResult.hasPrevious()) + previousResult(); + } } void nextResult() { @@ -561,14 +564,18 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct invalidateOptionsMenu(); } - private void saveTheFile() { + private void saveTheFile(boolean saveAs) { File file = new File(sFilePath); - if (!file.getName().isEmpty()) + if (!file.getName().isEmpty() && !saveAs) new SaveFileTask(this, sFilePath, pageSystem.getAllText(mEditor.getText() .toString()), currentEncoding).execute(); else { - NewFileDetailsDialog.newInstance - (pageSystem.getAllText(mEditor.getText().toString()), currentEncoding).show(getFragmentManager().beginTransaction(), "dialog"); + NewFileDetailsDialog.newInstance( + file.getParent(), + file.getName(), + pageSystem.getAllText(mEditor.getText().toString()), + currentEncoding + ).show(getFragmentManager().beginTransaction(), "dialog"); } } @@ -631,12 +638,6 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct verticalScroll.addView(mEditor); } - if (PreferenceHelper.getReadOnly(this)) { - getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); - } else { - getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); - } - verticalScroll.setScrollInterface(this); pageSystem = new PageSystem(this, this, "", null); @@ -655,7 +656,6 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct mEditor.resetVariables(); searchResult = null; - searchingText = false; invalidateOptionsMenu(); @@ -692,11 +692,11 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct || Intent.ACTION_PICK.equals(action) && type != null) { // Post event - onEvent(new EventBusEvents.NewFileToOpen(new File(intent - .getData().getPath()))); + newFileToOpen(new File(intent + .getData().getPath()), ""); } else if (Intent.ACTION_SEND.equals(action) && type != null) { if ("text/plain".equals(type)) { - onEvent(new EventBusEvents.NewFileToOpen(intent.getStringExtra(Intent.EXTRA_TEXT))); + newFileToOpen(null, intent.getStringExtra(Intent.EXTRA_TEXT)); } } } @@ -784,11 +784,11 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct //endregion //region EVENTBUS - void onEvent(final EventBusEvents.NewFileToOpen event) { + public void newFileToOpen(final File newFile, final String newFileText) { if (fileOpened && mEditor.canSaveFile()) { SaveFileDialog.newInstance(sFilePath, pageSystem.getAllText(mEditor - .getText().toString()), currentEncoding, true, event.getFile().getAbsolutePath()).show(getFragmentManager(), + .getText().toString()), currentEncoding, true, newFile.getAbsolutePath()).show(getFragmentManager(), "dialog"); return; } @@ -814,10 +814,13 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct @Override protected Void doInBackground(Void... params) { - file = event.getFile(); + file = newFile; + if (file == null) { + file = new File(""); + } try { if (!file.exists() || !file.isFile()) { - fileText = event.getFileText(); + fileText = newFileText; sFilePath = file.getAbsolutePath(); fileExtension = "txt"; return null; @@ -839,7 +842,7 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct File tempFile = new File(getFilesDir(), "temp.root.file"); if (!tempFile.exists()) tempFile.createNewFile(); - tb.copyFile(event.getFile().getAbsolutePath(), + tb.copyFile(file.getAbsolutePath(), tempFile.getAbsolutePath(), false, false); file = new File(tempFile.getAbsolutePath()); } @@ -879,13 +882,13 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct if (!message.isEmpty()) { Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show(); - onEvent(new EventBusEvents.CannotOpenAFile()); + cannotOpenFile(); } else { pageSystem = new PageSystem(MainActivity.this, MainActivity.this, fileText, new File(sFilePath)); currentEncoding = encoding; - onEvent(new EventBusEvents.AFileIsSelected(sFilePath)); + aFileWasSelected(sFilePath); showTextEditor(); @@ -904,11 +907,13 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct }.execute(); } - public void onEvent(EventBusEvents.SavedAFile event) { + public void savedAFile(String filePath) { - sFilePath = event.getPath(); + sFilePath = filePath; fileExtension = FilenameUtils.getExtension(sFilePath).toLowerCase(); + toolbar.setTitle(FilenameUtils.getName(sFilePath)); + mEditor.clearHistory(); mEditor.fileSaved(); invalidateOptionsMenu(); @@ -919,10 +924,8 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct e.printStackTrace(); } - refreshList(event.getPath(), true, false); - arrayAdapter.selectView(event.getPath()); - - showInterstitial(); + refreshList(filePath, true, false); + arrayAdapter.selectView(filePath); } /** @@ -931,7 +934,7 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct * * @param event The event called */ - void onEvent(EventBusEvents.CannotOpenAFile event) { + public void cannotOpenFile() { // mDrawerLayout.openDrawer(Gravity.LEFT); // @@ -942,13 +945,17 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct hideTextEditor(); } - public void onEvent(EventBusEvents.APreferenceValueWasChanged event) { + public void aPreferenceValueWasChanged(final PreferenceChangeType type) { + this.aPreferenceValueWasChanged(new ArrayList() {{add(type);}}); + } - if (event.hasType(EventBusEvents.APreferenceValueWasChanged.Type.THEME_CHANGE)) { + public void aPreferenceValueWasChanged(List types) { + + if (types.contains(PreferenceChangeType.THEME_CHANGE)) { ThemeUtils.setWindowsBackground(this); } - if (event.hasType(WRAP_CONTENT)) { + if (types.contains(PreferenceChangeType.WRAP_CONTENT)) { if (PreferenceHelper.getWrapContent(this)) { horizontalScroll.removeView(mEditor); verticalScroll.removeView(horizontalScroll); @@ -958,41 +965,42 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct verticalScroll.addView(horizontalScroll); horizontalScroll.addView(mEditor); } - } else if (event.hasType(LINE_NUMERS)) { + } else if (types.contains(PreferenceChangeType.LINE_NUMERS)) { mEditor.disableTextChangedListener(); mEditor.replaceTextKeepCursor(null, true); mEditor.enableTextChangedListener(); if (PreferenceHelper.getLineNumbers(this)) { - mEditor.setPadding(EditTextPadding.getPaddingWithLineNumbers(this, - PreferenceHelper.getFontSize(this)), - EditTextPadding.getPaddingTop(this), 0, 0); + mEditor.setPadding( + EditTextPadding.getPaddingWithLineNumbers(this, PreferenceHelper.getFontSize(this)), + EditTextPadding.getPaddingTop(this), + EditTextPadding.getPaddingTop(this), + 0); } else { - mEditor.setPadding(EditTextPadding.getPaddingWithoutLineNumbers(this) - , EditTextPadding.getPaddingTop(this), 0, 0); + mEditor.setPadding( + EditTextPadding.getPaddingWithoutLineNumbers(this), + EditTextPadding.getPaddingTop(this), + EditTextPadding.getPaddingTop(this), + 0); } - } else if (event.hasType(SYNTAX)) { + } else if (types.contains(PreferenceChangeType.SYNTAX)) { mEditor.disableTextChangedListener(); mEditor.replaceTextKeepCursor(null, true); mEditor.enableTextChangedListener(); - } else if (event.hasType(MONOSPACE)) { + } else if (types.contains(PreferenceChangeType.MONOSPACE)) { if (PreferenceHelper.getUseMonospace(this)) mEditor.setTypeface(Typeface.MONOSPACE); else mEditor.setTypeface(Typeface.DEFAULT); - } else if (event.hasType(THEME_CHANGE)) { + } else if (types.contains(PreferenceChangeType.THEME_CHANGE)) { if (PreferenceHelper.getLightTheme(this)) { mEditor.setTextColor(getResources().getColor(R.color.textColorInverted)); } else { mEditor.setTextColor(getResources().getColor(R.color.textColor)); } - } else if (event.hasType(TEXT_SUGGESTIONS) || event.hasType(READ_ONLY)) { + } else if (types.contains(PreferenceChangeType.TEXT_SUGGESTIONS) || types.contains(PreferenceChangeType.READ_ONLY)) { if (PreferenceHelper.getReadOnly(this)) { - getWindow().setSoftInputMode(WindowManager.LayoutParams - .SOFT_INPUT_STATE_ALWAYS_HIDDEN); mEditor.setReadOnly(true); } else { - getWindow().setSoftInputMode(WindowManager.LayoutParams - .SOFT_INPUT_STATE_UNSPECIFIED); mEditor.setReadOnly(false); if (PreferenceHelper.getSuggestionActive(this)) { mEditor.setInputType(InputType.TYPE_CLASS_TEXT | InputType @@ -1009,17 +1017,22 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct mEditor.setTypeface(Typeface.MONOSPACE); else mEditor.setTypeface(Typeface.DEFAULT); - } else if (event.hasType(FONT_SIZE)) { + } else if (types.contains(PreferenceChangeType.FONT_SIZE)) { if (PreferenceHelper.getLineNumbers(this)) { - mEditor.setPadding(EditTextPadding.getPaddingWithLineNumbers(this, - PreferenceHelper.getFontSize(this)), - EditTextPadding.getPaddingTop(this), 0, 0); + mEditor.setPadding( + EditTextPadding.getPaddingWithLineNumbers(this, PreferenceHelper.getFontSize(this)), + EditTextPadding.getPaddingTop(this), + EditTextPadding.getPaddingTop(this), + 0); } else { - mEditor.setPadding(EditTextPadding.getPaddingWithoutLineNumbers(this) - , EditTextPadding.getPaddingTop(this), 0, 0); + mEditor.setPadding( + EditTextPadding.getPaddingWithoutLineNumbers(this), + EditTextPadding.getPaddingTop(this), + EditTextPadding.getPaddingTop(this), + 0); } mEditor.setTextSize(PreferenceHelper.getFontSize(this)); - } else if (event.hasType(ENCODING)) { + } else if (types.contains(PreferenceChangeType.ENCODING)) { String oldEncoding, newEncoding; oldEncoding = currentEncoding; newEncoding = PreferenceHelper.getEncoding(this); @@ -1033,7 +1046,7 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct try { final byte[] oldText = mEditor.getText().toString().getBytes(oldEncoding); mEditor.disableTextChangedListener(); - mEditor.replaceTextKeepCursor(new String(oldText, "UTF-8"), true); + mEditor.replaceTextKeepCursor(new String(oldText, "UTF-16"), true); mEditor.enableTextChangedListener(); } catch (UnsupportedEncodingException ignored2) { } @@ -1041,24 +1054,43 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct } } - void onEvent(EventBusEvents.AFileIsSelected event) { - arrayAdapter.selectView(event.getPath()); + public void aFileWasSelected(String filePath) { + arrayAdapter.selectView(filePath); } - void onEvent(EventBusEvents.ClosedAFile event) { + public void closedTheFile() { arrayAdapter.selectView(""); } //endregion //region Calls from the layout public void OpenFile(View view) { - Intent subActivity = new Intent(MainActivity.this, SelectFileActivity.class); - subActivity.putExtra("action", SelectFileActivity.Actions.SelectFile); - AnimationUtils.startActivityWithScale(this, subActivity, true, SELECT_FILE_CODE, view); + +// if (Device.hasKitKatApi()) { +// // ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's file +// // browser. +// Intent intent = new Intent(Intent.ACTION_GET_CONTENT); +// +// // Filter to only show results that can be "opened", such as a +// // file (as opposed to a list of contacts or timezones) +// //intent.addCategory(Intent.CATEGORY_OPENABLE); +// +// // Filter to show only images, using the image MIME data type. +// // If one wanted to search for ogg vorbis files, the type would be "audio/ogg". +// // To search for all documents available via installed storage providers, +// // it would be "*/*". +// intent.setType("*/*"); +// +// startActivityForResult(intent, READ_REQUEST_CODE); +// } else { + Intent subActivity = new Intent(MainActivity.this, SelectFileActivity.class); + subActivity.putExtra("action", SelectFileActivity.Actions.SelectFile); + AnimationUtils.startActivityWithScale(this, subActivity, true, SELECT_FILE_CODE, view); +// } } public void CreateFile(View view) { - onEvent(new EventBusEvents.NewFileToOpen("")); // do not send the event to others + newFileToOpen(null, ""); // do not send the event to others } public void OpenInfo(View view) { @@ -1137,7 +1169,6 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct @Override public void onSearchDone(SearchResult searchResult) { MainActivity.searchResult = searchResult; - searchingText = true; invalidateOptionsMenu(); final int line = LineUtils.getLineFromIndex(searchResult.foundIndex.getFirst @@ -1165,7 +1196,7 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct @Override public void onPageChanged(int page) { pageSystemButtons.updateVisibility(false); - searchingText = false; + searchResult = null; mEditor.clearHistory(); invalidateOptionsMenu(); } @@ -1175,7 +1206,7 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct pageSystemButtons.updateVisibility(Math.abs(t) > 10); if (!PreferenceHelper.getSyntaxHighlight(this) || (mEditor.hasSelection() && - !searchingText) || updateHandler == null || colorRunnable_duringScroll == null) + searchResult == null) || updateHandler == null || colorRunnable_duringScroll == null) return; updateHandler.removeCallbacks(colorRunnable_duringEditing); @@ -1219,16 +1250,16 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct public void userDoesntWantToSave(boolean openNewFile, String pathOfNewFile) { Editor.canSaveFile = false; if(openNewFile) - onEvent(new EventBusEvents.NewFileToOpen(new File(pathOfNewFile))); + newFileToOpen(new File(pathOfNewFile), ""); else - onEvent(new EventBusEvents.CannotOpenAFile()); + cannotOpenFile(); } @Override public void CancelItem(int position, boolean andCloseOpenedFile) { refreshList(files.get(position).getAbsolutePath(), false, true); if (andCloseOpenedFile) - onEvent(new EventBusEvents.CannotOpenAFile()); + cannotOpenFile(); } //endregion @@ -1271,11 +1302,11 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct private static int firstVisibleIndex, firstColoredIndex; private static int deviceHeight; private static int editorHeight; - private static boolean[] hasNewLineArray; + private static boolean[] isGoodLineArray; private static int[] realLines; private static boolean wrapContent; - private static int lastLine; - private static int firstLine; + //private static int lastLine; + //private static int firstLine; private static CharSequence textToHighlight; private static int lastVisibleIndex; private static int i; @@ -1306,12 +1337,17 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct setTextColor(getResources().getColor(R.color.textColor)); } if (PreferenceHelper.getLineNumbers(getContext())) { - setPadding(EditTextPadding.getPaddingWithLineNumbers(getContext(), - PreferenceHelper.getFontSize(getContext())), - EditTextPadding.getPaddingTop(getContext()), 0, 0); + setPadding( + EditTextPadding.getPaddingWithLineNumbers(getContext(), PreferenceHelper.getFontSize(getContext())), + EditTextPadding.getPaddingTop(getContext()), + EditTextPadding.getPaddingTop(getContext()), + 0); } else { - setPadding(EditTextPadding.getPaddingWithoutLineNumbers(getContext()), - EditTextPadding.getPaddingTop(getContext()), 0, 0); + setPadding( + EditTextPadding.getPaddingWithoutLineNumbers(getContext()), + EditTextPadding.getPaddingTop(getContext()), + EditTextPadding.getPaddingTop(getContext()), + 0); } if (PreferenceHelper.getReadOnly(getContext())) { @@ -1397,24 +1433,20 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct lineUtils.updateHasNewLineArray(pageSystem .getStartingLine(), lineCount, getLayout(), getText().toString()); - hasNewLineArray = lineUtils.getToCountLinesArray(); + isGoodLineArray = lineUtils.getGoodLines(); realLines = lineUtils.getRealLines(); } - editorHeight = getHeight(); - firstLine = lineUtils.getFirstVisibleLine(verticalScroll, editorHeight, lineCount); - lastLine = lineUtils.getLastVisibleLine(verticalScroll, editorHeight, lineCount, deviceHeight); + //editorHeight = getHeight(); if (PreferenceHelper.getLineNumbers(getContext())) { wrapContent = PreferenceHelper.getWrapContent(getContext()); - i = firstLine; - while (i < lastLine) { + for (i = 0; i < lineCount; i++) { // if last line we count it anyway if (!wrapContent - || hasNewLineArray[i] - || i == lastLine - 1) { + || isGoodLineArray[i]) { realLine = realLines[i]; canvas.drawText(String.valueOf(realLine), @@ -1422,7 +1454,6 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct paddingTop + lineHeight * (i + 1), mPaintNumbers); } - i++; } } @@ -1456,7 +1487,7 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct return onTextContextMenuItem(ID_REDO); } case KeyEvent.KEYCODE_S: - ((MainActivity) getContext()).saveTheFile(); + ((MainActivity) getContext()).saveTheFile(false); return true; default: return super.onKeyDown(keyCode, event); @@ -1638,20 +1669,23 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct cursorPos = getSelectionStart(); cursorPosEnd = getSelectionEnd(); } + disableTextChangedListener(); - if (PreferenceHelper.getSyntaxHighlight(getContext())) + if (PreferenceHelper.getSyntaxHighlight(getContext())) { setText(highlight(textToUpdate == null ? getEditableText() : Editable.Factory .getInstance().newEditable(textToUpdate), textToUpdate != null)); - else - setText(textToUpdate == null ? getText().toString() : textToUpdate); + } + else { + setText(textToUpdate == null ? getEditableText() : textToUpdate); + } enableTextChangedListener(); if (mantainCursorPos) firstVisibleIndex = cursorPos; - if (firstVisibleIndex > -1) { + if (firstVisibleIndex > -1 && firstVisibleIndex < length()) { if (cursorPosEnd != cursorPos) setSelection(cursorPos, cursorPosEnd); else @@ -1667,7 +1701,7 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct removeTextChangedListener(mChangeListener); } - public CharSequence highlight(Editable editable, boolean newText) { + public Editable highlight(Editable editable, boolean newText) { editable.clearSpans(); if (editable.length() == 0) { @@ -1677,10 +1711,8 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct editorHeight = getHeight(); if (!newText && editorHeight > 0) { - firstLine = lineUtils.getFirstVisibleLine(verticalScroll, editorHeight, lineCount); - lastLine = lineUtils.getLastVisibleLine(verticalScroll, editorHeight, lineCount, deviceHeight); - firstVisibleIndex = getLayout().getLineStart(firstLine); - lastVisibleIndex = getLayout().getLineStart(lastLine); + firstVisibleIndex = getLayout().getLineStart(lineUtils.getFirstVisibleLine(verticalScroll, editorHeight, lineCount)); + lastVisibleIndex = getLayout().getLineStart(lineUtils.getLastVisibleLine(verticalScroll, editorHeight, lineCount, deviceHeight)); } else { firstVisibleIndex = 0; lastVisibleIndex = CHARS_TO_COLOR; @@ -1701,8 +1733,7 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct if (fileExtension.contains("htm") || fileExtension.contains("xml")) { - color(Patterns.HTML_OPEN_TAGS, editable, textToHighlight, firstColoredIndex); - color(Patterns.HTML_CLOSE_TAGS, editable, textToHighlight, firstColoredIndex); + color(Patterns.HTML_TAGS, editable, textToHighlight, firstColoredIndex); color(Patterns.HTML_ATTRS, editable, textToHighlight, firstColoredIndex); color(Patterns.GENERAL_STRINGS, editable, textToHighlight, firstColoredIndex); color(Patterns.XML_COMMENTS, editable, textToHighlight, firstColoredIndex); @@ -1768,8 +1799,7 @@ public abstract class MainActivity extends ActionBarActivity implements IHomeAct CharSequence textToHighlight, int start) { int color = 0; - if (pattern.equals(Patterns.HTML_OPEN_TAGS) - || pattern.equals(Patterns.HTML_CLOSE_TAGS) + if (pattern.equals(Patterns.HTML_TAGS) || pattern.equals(Patterns.GENERAL_KEYWORDS) || pattern.equals(Patterns.SQL_KEYWORDS) || pattern.equals(Patterns.PY_KEYWORDS) diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/EncodingDialog.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/EncodingDialog.java index 369d4a7..ee7d769 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/EncodingDialog.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/EncodingDialog.java @@ -60,6 +60,7 @@ public class EncodingDialog extends DialogFragment implements AdapterView.OnItem Constants.CHARSET_UTF_32BE, Constants.CHARSET_UTF_32LE, Constants.CHARSET_UTF_8, + "UTF-16", Constants.CHARSET_WINDOWS_1251, Constants.CHARSET_WINDOWS_1252, Constants.CHARSET_WINDOWS_1253, diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/FindTextDialog.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/FindTextDialog.java index a628871..ec3557c 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/FindTextDialog.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/FindTextDialog.java @@ -193,7 +193,7 @@ public class FindTextDialog extends DialogFragment { return; // else we return positions and other things else { - SearchResult searchResult = new SearchResult(foundIndex, textToFind.length(), replaceCheck.isChecked(), textToReplace.getText().toString()); + SearchResult searchResult = new SearchResult(foundIndex, textToFind.length(), replaceCheck.isChecked(), textToFind.getText().toString(), textToReplace.getText().toString()); searchDialogInterface.onSearchDone(searchResult); } } else { diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/NewFileDetailsDialog.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/NewFileDetailsDialog.java index 14e3b4f..d34d9a3 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/NewFileDetailsDialog.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/NewFileDetailsDialog.java @@ -24,16 +24,21 @@ import android.app.Dialog; import android.app.DialogFragment; import android.content.DialogInterface; import android.os.Bundle; +import android.text.TextUtils; import android.view.View; import android.view.WindowManager; +import android.widget.CheckBox; import android.widget.EditText; +import org.apache.commons.io.FileUtils; + import java.io.File; import sharedcode.turboeditor.R; import sharedcode.turboeditor.activity.MainActivity; import sharedcode.turboeditor.preferences.PreferenceHelper; import sharedcode.turboeditor.task.SaveFileTask; +import sharedcode.turboeditor.util.ViewUtils; import sharedcode.turboeditor.views.DialogHelper; // ... @@ -41,10 +46,13 @@ public class NewFileDetailsDialog extends DialogFragment { private EditText mName; private EditText mFolder; + private CheckBox mDeleteCurrentFile; - public static NewFileDetailsDialog newInstance(String fileText, String fileEncoding) { + public static NewFileDetailsDialog newInstance(String currentPath, String currentName, String fileText, String fileEncoding) { final NewFileDetailsDialog f = new NewFileDetailsDialog(); final Bundle args = new Bundle(); + args.putString("path", currentPath); + args.putString("name", currentName); args.putString("fileText", fileText); args.putString("fileEncoding", fileEncoding); f.setArguments(args); @@ -55,15 +63,29 @@ public class NewFileDetailsDialog extends DialogFragment { public Dialog onCreateDialog(Bundle savedInstanceState) { View view = new DialogHelper.Builder(getActivity()) - .setTitle(R.string.file) + .setTitle(R.string.save_as) .setView(R.layout.dialog_fragment_new_file_details) .createSkeletonView(); this.mName = (EditText) view.findViewById(android.R.id.text1); this.mFolder = (EditText) view.findViewById(android.R.id.text2); - this.mName.setText(".txt"); - this.mFolder.setText(PreferenceHelper.getWorkingFolder(getActivity())); + boolean noName = TextUtils.isEmpty(getArguments().getString("name")); + boolean noPath = TextUtils.isEmpty(getArguments().getString("path")); + + if (noName) { + this.mName.setText(".txt"); + } else { + this.mName.setText(getArguments().getString("name")); + } + if (noPath) { + this.mFolder.setText(PreferenceHelper.getWorkingFolder(getActivity())); + } else { + this.mFolder.setText(getArguments().getString("path")); + } + + this.mDeleteCurrentFile = (CheckBox) view.findViewById(R.id.delete_current_file); + ViewUtils.setVisible(mDeleteCurrentFile, !noName); // Show soft keyboard automatically this.mName.requestFocus(); @@ -76,6 +98,11 @@ public class NewFileDetailsDialog extends DialogFragment { new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { + + if (mDeleteCurrentFile.isChecked()) { + FileUtils.deleteQuietly(new File(getArguments().getString("path"), getArguments().getString("name"))); + } + if (!mName.getText().toString().isEmpty() && !mFolder.getText().toString().isEmpty()) { File file = new File(mFolder.getText().toString(), mName.getText().toString()); new SaveFileTask((MainActivity) getActivity(), file.getPath(), getArguments().getString("fileText"), getArguments().getString("fileEncoding")).execute(); diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/SaveFileDialog.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/SaveFileDialog.java index bd7f44c..c60f236 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/SaveFileDialog.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/dialogfragment/SaveFileDialog.java @@ -80,7 +80,7 @@ public class SaveFileDialog extends DialogFragment { encoding).execute(); else { NewFileDetailsDialog dialogFrag = - NewFileDetailsDialog.newInstance(text, + NewFileDetailsDialog.newInstance("","",text, encoding); dialogFrag.show(getFragmentManager().beginTransaction(), "dialog"); diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/Donation.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/Donation.java deleted file mode 100644 index 2a0bc10..0000000 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/Donation.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Turbo Editor is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package sharedcode.turboeditor.iab; - - -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; - -/** - * The helper class of donation item. - * - * @author Artem Chepurnoy - */ -public class Donation { - - public final int amount; - public final String sku; - public final String text; - - public Donation(int amount, String text) { - this.amount = amount; - this.text = text; - - // Notice that all of them are defined in - // my Play Store's account! - this.sku = "donation_" + amount; - } - - /** - * {@inheritDoc} - */ - @Override - public int hashCode() { - return new HashCodeBuilder(9, 51) - .append(amount) - .append(text) - .append(sku) - .toHashCode(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean equals(Object o) { - if (o == null) - return false; - if (o == this) - return true; - if (!(o instanceof Donation)) - return false; - - Donation donation = (Donation) o; - return new EqualsBuilder() - .append(amount, donation.amount) - .append(text, donation.text) - .append(sku, donation.sku) - .isEquals(); - } - -} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/DonationAdapter.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/DonationAdapter.java deleted file mode 100644 index 958f807..0000000 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/DonationAdapter.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Turbo Editor is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package sharedcode.turboeditor.iab; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Paint; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.TextView; - -import java.util.HashSet; - -import sharedcode.turboeditor.R; - -/** - * Created by achep on 06.05.14 for AcDisplay. - * - * @author Artem Chepurnoy - */ -public class DonationAdapter extends ArrayAdapter { - - private final HashSet mInventorySet; - private final LayoutInflater mInflater; - private final String mDonationAmountLabel; - - private final int mColorNormal; - private final int mColorPurchased; - - public DonationAdapter(Context context, Donation[] items, HashSet inventory) { - super(context, 0, items); - - mInventorySet = inventory; - mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - - Resources res = context.getResources(); - mDonationAmountLabel = res.getString(R.string.donation_item_label); - mColorNormal = res.getColor(R.color.donation_normal); - mColorPurchased = res.getColor(R.color.donation_purchased); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - final Donation donation = getItem(position); - final Holder holder; - final View view; - - if (convertView == null) { - holder = new Holder(); - view = mInflater.inflate(R.layout.donation_iab_item, parent, false); - assert view != null; - - holder.title = (TextView) view.findViewById(android.R.id.title); - holder.summary = (TextView) view.findViewById(android.R.id.summary); - - view.setTag(holder); - } else { - view = convertView; - holder = (Holder) view.getTag(); - } - - boolean bought = mInventorySet.contains(donation.sku); - - String amount = Integer.toString(donation.amount); - holder.title.setText(String.format(mDonationAmountLabel, amount)); - holder.title.setTextColor(bought ? mColorNormal : mColorPurchased); - holder.summary.setText(donation.text); - holder.summary.setPaintFlags(bought - ? holder.summary.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG - : holder.summary.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG)); - - return view; - } - - private static class Holder { - TextView title; - TextView summary; - } -} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/DonationFragment.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/DonationFragment.java deleted file mode 100644 index 12e592f..0000000 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/DonationFragment.java +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Turbo Editor is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package sharedcode.turboeditor.iab; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.content.ActivityNotFoundException; -import android.content.DialogInterface; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.text.Html; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.method.LinkMovementMethod; -import android.text.style.ImageSpan; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.Button; -import android.widget.GridView; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.TextView; - -import java.util.HashSet; - -import sharedcode.turboeditor.R; -import sharedcode.turboeditor.iab.utils.IabHelper; -import sharedcode.turboeditor.iab.utils.IabResult; -import sharedcode.turboeditor.iab.utils.Inventory; -import sharedcode.turboeditor.iab.utils.Purchase; -import sharedcode.turboeditor.preferences.PreferenceHelper; -import sharedcode.turboeditor.util.Build; -import sharedcode.turboeditor.util.ToastUtils; -import sharedcode.turboeditor.util.ViewUtils; -import sharedcode.turboeditor.views.DialogHelper; - -/** - * Fragment that represents an ability to donate to me. Be sure to redirect - * {@link android.app.Activity#onActivityResult(int, int, android.content.Intent)} - * to this fragment! - * - * @author Artem Chepurnoy - */ -public class DonationFragment extends DialogFragment { - - public static final int RC_REQUEST = 10001; - private static final String TAG = "DonationFragment"; - private final HashSet mInventorySet = new HashSet<>(); - private GridView mGridView; - private ProgressBar mProgressBar; - private TextView mError; - private IabHelper mHelper; - private final IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = - new IabHelper.OnIabPurchaseFinishedListener() { - public void onIabPurchaseFinished(IabResult result, Purchase purchase) { - if (mHelper == null) return; - if (result.isFailure()) { - complain("Error purchasing: " + result); - setWaitScreen(false); - return; - } - - if (!verifyDeveloperPayload(purchase)) { - complain("Error purchasing. Authenticity verification failed."); - setWaitScreen(false); - return; - } - - // else, it is a success, the user has donated! - String sku = purchase.getSku(); - mInventorySet.add(sku); - PreferenceHelper.setHasDonated(getActivity(), true); - } - }; - private Donation[] mDonationList; - private final IabHelper.QueryInventoryFinishedListener mGotInventoryListener = - new IabHelper.QueryInventoryFinishedListener() { - public void onQueryInventoryFinished(IabResult result, Inventory inventory) { - if (mHelper == null) return; - if (result.isFailure()) { - complain("Failed to query inventory: " + result); - return; - } - - mInventorySet.clear(); - for (Donation donation : mDonationList) { - Purchase purchase = inventory.getPurchase(donation.sku); - boolean isBought = (purchase != null && verifyDeveloperPayload(purchase)); - - if (isBought) { - mInventorySet.add(donation.sku); - PreferenceHelper.setHasDonated(getActivity(), true); - } - } - - /* - // Fake items to debug user interface. - mInventorySet.add(mDonationList[0].sku); - mInventorySet.add(mDonationList[1].sku); - mInventorySet.add(mDonationList[2].sku); - */ - - updateUi(); - setWaitScreen(false); - } - }; - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - mDonationList = DonationItems.get(getResources()); - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - Activity activity = getActivity(); - assert activity != null; - - View view = new DialogHelper.Builder(activity) - .setTitle(R.string.donation_title) - .setView(R.layout.donation_dialog) - .createSkeletonView(); - AlertDialog.Builder builder = new AlertDialog.Builder(activity) - .setView(view) - .setNegativeButton(android.R.string.cancel, null); - - TextView info = (TextView) view.findViewById(R.id.info); - info.setText(Html.fromHtml(getString(R.string.donation_info))); - info.setMovementMethod(new LinkMovementMethod()); - - mError = (TextView) view.findViewById(R.id.error); - mProgressBar = (ProgressBar) view.findViewById(android.R.id.progress); - mGridView = (GridView) view.findViewById(R.id.grid); - mGridView.setAdapter(new DonationAdapter(getActivity(), mDonationList, mInventorySet)); - mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - DonationAdapter adapter = (DonationAdapter) parent.getAdapter(); - Donation donation = adapter.getItem(position); - - if (!mInventorySet.contains(donation.sku)) { - /** - * See {@link sharedcode.turboeditor.iab.DonationFragment#verifyDeveloperPayload(Purchase)}. - */ - String payload = ""; - try { - mHelper.launchPurchaseFlow( - getActivity(), donation.sku, RC_REQUEST, - mPurchaseFinishedListener, payload); - } catch (Exception e) { - ToastUtils.showShort(getActivity(), "Failed to launch a purchase flow."); - } - } else { - ToastUtils.showShort(getActivity(), getString(R.string.donation_item_bought)); - } - } - }); - - final AlertDialog alertDialog; - - // Show PayPal button. - final Intent paypalIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(Build.Links.DONATE)); - builder.setNeutralButton(R.string.paypal, null); - - alertDialog = builder.create(); - alertDialog.setOnShowListener(new DialogInterface.OnShowListener() { - - @Override - public void onShow(DialogInterface dialog) { - Data[] datas = new Data[]{ - new Data( - alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL), - paypalIntent, R.drawable.ic_action_paypal) - }; - - ImageSpan span; - SpannableString text; - for (final Data data : datas) { - final Button btn = data.button; - if (btn != null) { - span = new ImageSpan(getActivity(), data.iconResource); - - // Replace text with an icon. - // This is a workaround to fix compound button's aligment. - text = new SpannableString(" "); - text.setSpan(span, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - btn.setText(text); - - // Eat default weight. - btn.setLayoutParams(new LinearLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT)); - - btn.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - startPaymentIntentWithWarningAlertDialog(data.intent); - } - }); - } - } - } - - final class Data { - - private final Button button; - private final Intent intent; - private final int iconResource; - - private Data(Button button, Intent intent, int iconResource) { - this.button = button; - this.intent = intent; - this.iconResource = iconResource; - } - } - }); - - initBilling(); - - return alertDialog; - } - - /** - * Shows a warning alert dialog to note, that those methods - * may suck hard and nobody will care about it.
- * Starts an intent if user is agree with it. - */ - private void startPaymentIntentWithWarningAlertDialog(final Intent intent) { - CharSequence messageText = getString(R.string.donation_no_responsibility); - new DialogHelper.Builder(getActivity()) - .setMessage(messageText) - .wrap() - .setNegativeButton(android.R.string.cancel, null) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - try { - startActivity(intent); - dismiss(); // Dismiss main fragment - } catch (ActivityNotFoundException e) { /* hell no */ } - } - }) - .create() - .show(); - } - - private void setWaitScreen(boolean loading) { - ViewUtils.setVisible(mProgressBar, loading); - ViewUtils.setVisible(mGridView, !loading); - ViewUtils.setVisible(mError, false); - } - - private void setErrorScreen(String errorMessage, final Runnable runnable) { - mProgressBar.setVisibility(View.GONE); - mGridView.setVisibility(View.GONE); - mError.setVisibility(View.VISIBLE); - mError.setText(errorMessage); - mError.setOnClickListener(runnable != null ? new View.OnClickListener() { - @Override - public void onClick(View v) { - runnable.run(); - } - } : null); - } - - /** - * Updates GUI to display changes. - */ - private void updateUi() { - DonationAdapter adapter = (DonationAdapter) mGridView.getAdapter(); - adapter.notifyDataSetChanged(); - } - - @Override - public void onDestroy() { - super.onDestroy(); - disposeBilling(); - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (mHelper.handleActivityResult(requestCode, resultCode, data)) { - return; - } - - super.onActivityResult(requestCode, resultCode, data); - } - - /** - * Releases billing service. - * - * @see #initBilling() - */ - private void disposeBilling() { - if (mHelper != null) { - mHelper.dispose(); - mHelper = null; - } - } - - /** - * Make sure you call {@link #disposeBilling()}! - * - * @see #disposeBilling() - */ - private void initBilling() { - setWaitScreen(true); - disposeBilling(); - - String base64EncodedPublicKey = Build.GOOGLE_PLAY_PUBLIC_KEY; - mHelper = new IabHelper(getActivity(), base64EncodedPublicKey); - mHelper.enableDebugLogging(Build.DEBUG); - mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { - public void onIabSetupFinished(IabResult result) { - if (mHelper == null) return; - if (!result.isSuccess()) { - setErrorScreen(getString(R.string.donation_error_iab_setup), new Runnable() { - @Override - public void run() { - // Try to initialize billings again. - initBilling(); - } - }); - return; - } - - setWaitScreen(false); - mHelper.queryInventoryAsync(mGotInventoryListener); - } - }); - } - - private boolean verifyDeveloperPayload(Purchase purchase) { - // TODO: This method itself is a big question. - // Personally, I think that this whole ‘best practices’ part - // is confusing and is trying to make you do work that the API - // should really be doing. Since the purchase is tied to a Google account, - // and the Play Store obviously saves this information, they should - // just give you this in the purchase details. Getting a proper user ID - // requires additional permissions that you shouldn’t need to add just - // to cover for the deficiencies of the IAB API. - return true; - } - - private void complain(String message) { - ToastUtils.showShort(getActivity(), message); - } - -} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/DonationItems.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/DonationItems.java deleted file mode 100644 index 34a3db1..0000000 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/DonationItems.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Turbo Editor is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package sharedcode.turboeditor.iab; - -import android.content.res.Resources; - -import sharedcode.turboeditor.R; - -/** - * Created by achep on 07.05.14 for AcDisplay. - * - * @author Artem Chepurnoy - */ -public class DonationItems { - - public static Donation[] get(Resources res) { - int[] data = new int[]{ - 2, R.string.donation_2, - 4, R.string.donation_4, - 10, R.string.donation_10, - 20, R.string.donation_20, - 50, R.string.donation_50, - 99, R.string.donation_99, - }; - - Donation[] donation = new Donation[data.length / 2]; - - int length = donation.length; - for (int i = 0; i < length; i++) { - donation[i] = new Donation(data[i * 2], - res.getString(data[i * 2 + 1])); - } - return donation; - } - -} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Base64.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Base64.java deleted file mode 100644 index 94b7d50..0000000 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Base64.java +++ /dev/null @@ -1,582 +0,0 @@ -// Portions copyright 2002, Google, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package sharedcode.turboeditor.iab.utils; - -// This code was converted from code at http://iharder.sourceforge.net/base64/ -// Lots of extraneous features were removed. -/* The original code said: - *

- * I am placing this code in the Public Domain. Do with it as you will. - * This software comes with no guarantees or warranties but with - * plenty of well-wishing instead! - * Please visit - * http://iharder.net/xmlizable - * periodically to check for updates or to contribute improvements. - *

- * - * @author Robert Harder - * @author rharder@usa.net - * @version 1.3 - */ - -/** - * Base64 converter class. This code is not a complete MIME encoder; - * it simply converts binary data to base64 data and back. - *

- *

Note {@link CharBase64} is a GWT-compatible implementation of this - * class. - */ -public class Base64 { - /** - * Specify encoding (value is {@code true}). - */ - public final static boolean ENCODE = true; - - /** - * Specify decoding (value is {@code false}). - */ - public final static boolean DECODE = false; - - /** - * The equals sign (=) as a byte. - */ - private final static byte EQUALS_SIGN = (byte) '='; - - /** - * The new line character (\n) as a byte. - */ - private final static byte NEW_LINE = (byte) '\n'; - - /** - * The 64 valid Base64 values. - */ - private final static byte[] ALPHABET = - {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', - (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', - (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', - (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', - (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', - (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', - (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', - (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', - (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', - (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', - (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', - (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', - (byte) '9', (byte) '+', (byte) '/'}; - - /** - * The 64 valid web safe Base64 values. - */ - private final static byte[] WEBSAFE_ALPHABET = - {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', - (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', - (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', - (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', - (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', - (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', - (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', - (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', - (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', - (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', - (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', - (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', - (byte) '9', (byte) '-', (byte) '_'}; - - /** - * Translates a Base64 value to either its 6-bit reconstruction value - * or a negative number indicating some other meaning. - */ - private final static byte[] DECODABET = {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 - -5, -5, // Whitespace: Tab and Linefeed - -9, -9, // Decimal 11 - 12 - -5, // Whitespace: Carriage Return - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 - -9, -9, -9, -9, -9, // Decimal 27 - 31 - -5, // Whitespace: Space - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42 - 62, // Plus sign at decimal 43 - -9, -9, -9, // Decimal 44 - 46 - 63, // Slash at decimal 47 - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine - -9, -9, -9, // Decimal 58 - 60 - -1, // Equals sign at decimal 61 - -9, -9, -9, // Decimal 62 - 64 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z' - -9, -9, -9, -9, -9, -9, // Decimal 91 - 96 - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z' - -9, -9, -9, -9, -9 // Decimal 123 - 127 - /* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ - }; - - /** - * The web safe decodabet - */ - private final static byte[] WEBSAFE_DECODABET = - {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 - -5, -5, // Whitespace: Tab and Linefeed - -9, -9, // Decimal 11 - 12 - -5, // Whitespace: Carriage Return - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 - -9, -9, -9, -9, -9, // Decimal 27 - 31 - -5, // Whitespace: Space - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 44 - 62, // Dash '-' sign at decimal 45 - -9, -9, // Decimal 46-47 - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine - -9, -9, -9, // Decimal 58 - 60 - -1, // Equals sign at decimal 61 - -9, -9, -9, // Decimal 62 - 64 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z' - -9, -9, -9, -9, // Decimal 91-94 - 63, // Underscore '_' at decimal 95 - -9, // Decimal 96 - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z' - -9, -9, -9, -9, -9 // Decimal 123 - 127 - /* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ - }; - - // Indicates white space in encoding - private final static byte WHITE_SPACE_ENC = -5; - // Indicates equals sign in encoding - private final static byte EQUALS_SIGN_ENC = -1; - - /** - * Defeats instantiation. - */ - private Base64() { - } - - /* ******** E N C O D I N G M E T H O D S ******** */ - - /** - * Encodes up to three bytes of the array source - * and writes the resulting four Base64 bytes to destination. - * The source and destination arrays can be manipulated - * anywhere along their length by specifying - * srcOffset and destOffset. - * This method does not check to make sure your arrays - * are large enough to accommodate srcOffset + 3 for - * the source array or destOffset + 4 for - * the destination array. - * The actual number of significant bytes in your array is - * given by numSigBytes. - * - * @param source the array to convert - * @param srcOffset the index where conversion begins - * @param numSigBytes the number of significant bytes in your array - * @param destination the array to hold the conversion - * @param destOffset the index where output will be put - * @param alphabet is the encoding alphabet - * @return the destination array - * @since 1.3 - */ - private static byte[] encode3to4(byte[] source, int srcOffset, - int numSigBytes, byte[] destination, int destOffset, byte[] alphabet) { - // 1 2 3 - // 01234567890123456789012345678901 Bit position - // --------000000001111111122222222 Array position from threeBytes - // --------| || || || | Six bit groups to index alphabet - // >>18 >>12 >> 6 >> 0 Right shift necessary - // 0x3f 0x3f 0x3f Additional AND - - // Create buffer with zero-padding if there are only one or two - // significant bytes passed in the array. - // We have to shift left 24 in order to flush out the 1's that appear - // when Java treats a value as negative that is cast from a byte to an int. - int inBuff = - (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0) - | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0) - | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0); - - switch (numSigBytes) { - case 3: - destination[destOffset] = alphabet[(inBuff >>> 18)]; - destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f]; - destination[destOffset + 3] = alphabet[(inBuff) & 0x3f]; - return destination; - case 2: - destination[destOffset] = alphabet[(inBuff >>> 18)]; - destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f]; - destination[destOffset + 3] = EQUALS_SIGN; - return destination; - case 1: - destination[destOffset] = alphabet[(inBuff >>> 18)]; - destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = EQUALS_SIGN; - destination[destOffset + 3] = EQUALS_SIGN; - return destination; - default: - return destination; - } // end switch - } // end encode3to4 - - /** - * Encodes a byte array into Base64 notation. - * Equivalent to calling - * {@code encodeBytes(source, 0, source.length)} - * - * @param source The data to convert - * @since 1.4 - */ - public static String encode(byte[] source) { - return encode(source, 0, source.length, ALPHABET, true); - } - - /** - * Encodes a byte array into web safe Base64 notation. - * - * @param source The data to convert - * @param doPadding is {@code true} to pad result with '=' chars - * if it does not fall on 3 byte boundaries - */ - public static String encodeWebSafe(byte[] source, boolean doPadding) { - return encode(source, 0, source.length, WEBSAFE_ALPHABET, doPadding); - } - - /** - * Encodes a byte array into Base64 notation. - * - * @param source the data to convert - * @param off offset in array where conversion should begin - * @param len length of data to convert - * @param alphabet the encoding alphabet - * @param doPadding is {@code true} to pad result with '=' chars - * if it does not fall on 3 byte boundaries - * @since 1.4 - */ - public static String encode(byte[] source, int off, int len, byte[] alphabet, - boolean doPadding) { - byte[] outBuff = encode(source, off, len, alphabet, Integer.MAX_VALUE); - int outLen = outBuff.length; - - // If doPadding is false, set length to truncate '=' - // padding characters - while (doPadding == false && outLen > 0) { - if (outBuff[outLen - 1] != '=') { - break; - } - outLen -= 1; - } - - return new String(outBuff, 0, outLen); - } - - /** - * Encodes a byte array into Base64 notation. - * - * @param source the data to convert - * @param off offset in array where conversion should begin - * @param len length of data to convert - * @param alphabet is the encoding alphabet - * @param maxLineLength maximum length of one line. - * @return the BASE64-encoded byte array - */ - public static byte[] encode(byte[] source, int off, int len, byte[] alphabet, - int maxLineLength) { - int lenDiv3 = (len + 2) / 3; // ceil(len / 3) - int len43 = lenDiv3 * 4; - byte[] outBuff = new byte[len43 // Main 4:3 - + (len43 / maxLineLength)]; // New lines - - int d = 0; - int e = 0; - int len2 = len - 2; - int lineLength = 0; - for (; d < len2; d += 3, e += 4) { - - // The following block of code is the same as - // encode3to4( source, d + off, 3, outBuff, e, alphabet ); - // but inlined for faster encoding (~20% improvement) - int inBuff = - ((source[d + off] << 24) >>> 8) - | ((source[d + 1 + off] << 24) >>> 16) - | ((source[d + 2 + off] << 24) >>> 24); - outBuff[e] = alphabet[(inBuff >>> 18)]; - outBuff[e + 1] = alphabet[(inBuff >>> 12) & 0x3f]; - outBuff[e + 2] = alphabet[(inBuff >>> 6) & 0x3f]; - outBuff[e + 3] = alphabet[(inBuff) & 0x3f]; - - lineLength += 4; - if (lineLength == maxLineLength) { - outBuff[e + 4] = NEW_LINE; - e++; - lineLength = 0; - } // end if: end of line - } // end for: each piece of array - - if (d < len) { - encode3to4(source, d + off, len - d, outBuff, e, alphabet); - - lineLength += 4; - if (lineLength == maxLineLength) { - // Add a last newline - outBuff[e + 4] = NEW_LINE; - e++; - } - e += 4; - } - - assert (e == outBuff.length); - return outBuff; - } - - - /* ******** D E C O D I N G M E T H O D S ******** */ - - - /** - * Decodes four bytes from array source - * and writes the resulting bytes (up to three of them) - * to destination. - * The source and destination arrays can be manipulated - * anywhere along their length by specifying - * srcOffset and destOffset. - * This method does not check to make sure your arrays - * are large enough to accommodate srcOffset + 4 for - * the source array or destOffset + 3 for - * the destination array. - * This method returns the actual number of bytes that - * were converted from the Base64 encoding. - * - * @param source the array to convert - * @param srcOffset the index where conversion begins - * @param destination the array to hold the conversion - * @param destOffset the index where output will be put - * @param decodabet the decodabet for decoding Base64 content - * @return the number of decoded bytes converted - * @since 1.3 - */ - private static int decode4to3(byte[] source, int srcOffset, - byte[] destination, int destOffset, byte[] decodabet) { - // Example: Dk== - if (source[srcOffset + 2] == EQUALS_SIGN) { - int outBuff = - ((decodabet[source[srcOffset]] << 24) >>> 6) - | ((decodabet[source[srcOffset + 1]] << 24) >>> 12); - - destination[destOffset] = (byte) (outBuff >>> 16); - return 1; - } else if (source[srcOffset + 3] == EQUALS_SIGN) { - // Example: DkL= - int outBuff = - ((decodabet[source[srcOffset]] << 24) >>> 6) - | ((decodabet[source[srcOffset + 1]] << 24) >>> 12) - | ((decodabet[source[srcOffset + 2]] << 24) >>> 18); - - destination[destOffset] = (byte) (outBuff >>> 16); - destination[destOffset + 1] = (byte) (outBuff >>> 8); - return 2; - } else { - // Example: DkLE - int outBuff = - ((decodabet[source[srcOffset]] << 24) >>> 6) - | ((decodabet[source[srcOffset + 1]] << 24) >>> 12) - | ((decodabet[source[srcOffset + 2]] << 24) >>> 18) - | ((decodabet[source[srcOffset + 3]] << 24) >>> 24); - - destination[destOffset] = (byte) (outBuff >> 16); - destination[destOffset + 1] = (byte) (outBuff >> 8); - destination[destOffset + 2] = (byte) (outBuff); - return 3; - } - } // end decodeToBytes - - - /** - * Decodes data from Base64 notation. - * - * @param s the string to decode (decoded in default encoding) - * @return the decoded data - * @since 1.4 - */ - public static byte[] decode(String s) throws Base64DecoderException { - byte[] bytes = s.getBytes(); - return decode(bytes, 0, bytes.length); - } - - /** - * Decodes data from web safe Base64 notation. - * Web safe encoding uses '-' instead of '+', '_' instead of '/' - * - * @param s the string to decode (decoded in default encoding) - * @return the decoded data - */ - public static byte[] decodeWebSafe(String s) throws Base64DecoderException { - byte[] bytes = s.getBytes(); - return decodeWebSafe(bytes, 0, bytes.length); - } - - /** - * Decodes Base64 content in byte array format and returns - * the decoded byte array. - * - * @param source The Base64 encoded data - * @return decoded data - * @throws Base64DecoderException - * @since 1.3 - */ - public static byte[] decode(byte[] source) throws Base64DecoderException { - return decode(source, 0, source.length); - } - - /** - * Decodes web safe Base64 content in byte array format and returns - * the decoded data. - * Web safe encoding uses '-' instead of '+', '_' instead of '/' - * - * @param source the string to decode (decoded in default encoding) - * @return the decoded data - */ - public static byte[] decodeWebSafe(byte[] source) - throws Base64DecoderException { - return decodeWebSafe(source, 0, source.length); - } - - /** - * Decodes Base64 content in byte array format and returns - * the decoded byte array. - * - * @param source the Base64 encoded data - * @param off the offset of where to begin decoding - * @param len the length of characters to decode - * @return decoded data - * @throws Base64DecoderException - * @since 1.3 - */ - public static byte[] decode(byte[] source, int off, int len) - throws Base64DecoderException { - return decode(source, off, len, DECODABET); - } - - /** - * Decodes web safe Base64 content in byte array format and returns - * the decoded byte array. - * Web safe encoding uses '-' instead of '+', '_' instead of '/' - * - * @param source the Base64 encoded data - * @param off the offset of where to begin decoding - * @param len the length of characters to decode - * @return decoded data - */ - public static byte[] decodeWebSafe(byte[] source, int off, int len) - throws Base64DecoderException { - return decode(source, off, len, WEBSAFE_DECODABET); - } - - /** - * Decodes Base64 content using the supplied decodabet and returns - * the decoded byte array. - * - * @param source the Base64 encoded data - * @param off the offset of where to begin decoding - * @param len the length of characters to decode - * @param decodabet the decodabet for decoding Base64 content - * @return decoded data - */ - public static byte[] decode(byte[] source, int off, int len, byte[] decodabet) - throws Base64DecoderException { - int len34 = len * 3 / 4; - byte[] outBuff = new byte[2 + len34]; // Upper limit on size of output - int outBuffPosn = 0; - - byte[] b4 = new byte[4]; - int b4Posn = 0; - int i = 0; - byte sbiCrop = 0; - byte sbiDecode = 0; - for (i = 0; i < len; i++) { - sbiCrop = (byte) (source[i + off] & 0x7f); // Only the low seven bits - sbiDecode = decodabet[sbiCrop]; - - if (sbiDecode >= WHITE_SPACE_ENC) { // White space Equals sign or better - if (sbiDecode >= EQUALS_SIGN_ENC) { - // An equals sign (for padding) must not occur at position 0 or 1 - // and must be the last byte[s] in the encoded value - if (sbiCrop == EQUALS_SIGN) { - int bytesLeft = len - i; - byte lastByte = (byte) (source[len - 1 + off] & 0x7f); - if (b4Posn == 0 || b4Posn == 1) { - throw new Base64DecoderException( - "invalid padding byte '=' at byte offset " + i); - } else if ((b4Posn == 3 && bytesLeft > 2) - || (b4Posn == 4 && bytesLeft > 1)) { - throw new Base64DecoderException( - "padding byte '=' falsely signals end of encoded value " - + "at offset " + i - ); - } else if (lastByte != EQUALS_SIGN && lastByte != NEW_LINE) { - throw new Base64DecoderException( - "encoded value has invalid trailing byte"); - } - break; - } - - b4[b4Posn++] = sbiCrop; - if (b4Posn == 4) { - outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet); - b4Posn = 0; - } - } - } else { - throw new Base64DecoderException("Bad Base64 input character at " + i - + ": " + source[i + off] + "(decimal)"); - } - } - - // Because web safe encoding allows non padding base64 encodes, we - // need to pad the rest of the b4 buffer with equal signs when - // b4Posn != 0. There can be at most 2 equal signs at the end of - // four characters, so the b4 buffer must have two or three - // characters. This also catches the case where the input is - // padded with EQUALS_SIGN - if (b4Posn != 0) { - if (b4Posn == 1) { - throw new Base64DecoderException("single trailing character at offset " - + (len - 1)); - } - b4[b4Posn++] = EQUALS_SIGN; - outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet); - } - - byte[] out = new byte[outBuffPosn]; - System.arraycopy(outBuff, 0, out, 0, outBuffPosn); - return out; - } -} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/IabException.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/IabException.java deleted file mode 100644 index 2e00564..0000000 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/IabException.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Turbo Editor is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package sharedcode.turboeditor.iab.utils; - -/** - * Exception thrown when something went wrong with in-app billing. - * An IabException has an associated IabResult (an error). - * To get the IAB result that caused this exception to be thrown, - * call {@link #getResult()}. - */ -public class IabException extends Exception { - IabResult mResult; - - public IabException(IabResult r) { - this(r, null); - } - - public IabException(int response, String message) { - this(new IabResult(response, message)); - } - - public IabException(IabResult r, Exception cause) { - super(r.getMessage(), cause); - mResult = r; - } - - public IabException(int response, String message, Exception cause) { - this(new IabResult(response, message), cause); - } - - /** - * Returns the IAB result (error) that this exception signals. - */ - public IabResult getResult() { - return mResult; - } -} \ No newline at end of file diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/IabHelper.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/IabHelper.java deleted file mode 100644 index 61060f0..0000000 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/IabHelper.java +++ /dev/null @@ -1,966 +0,0 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Turbo Editor is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package sharedcode.turboeditor.iab.utils; - -import android.app.Activity; -import android.app.PendingIntent; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentSender.SendIntentException; -import android.content.ServiceConnection; -import android.content.pm.ResolveInfo; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.text.TextUtils; -import android.util.Log; - - -import org.json.JSONException; -import com.android.vending.billing.*; - -import java.util.ArrayList; -import java.util.List; - - -/** - * Provides convenience methods for in-app billing. You can create one instance of this - * class for your application and use it to process in-app billing operations. - * It provides synchronous (blocking) and asynchronous (non-blocking) methods for - * many common in-app billing operations, as well as automatic signature - * verification. - *

- * After instantiating, you must perform setup in order to start using the object. - * To perform setup, call the {@link #startSetup} method and provide a listener; - * that listener will be notified when setup is complete, after which (and not before) - * you may call other methods. - *

- * After setup is complete, you will typically want to request an inventory of owned - * items and subscriptions. See {@link #queryInventory}, {@link #queryInventoryAsync} - * and related methods. - *

- * When you are done with this object, don't forget to call {@link #dispose} - * to ensure proper cleanup. This object holds a binding to the in-app billing - * service, which will leak unless you dispose of it correctly. If you created - * the object on an Activity's onCreate method, then the recommended - * place to dispose of it is the Activity's onDestroy method. - *

- * A note about threading: When using this object from a background thread, you may - * call the blocking versions of methods; when using from a UI thread, call - * only the asynchronous versions and handle the results via callbacks. - * Also, notice that you can only call one asynchronous operation at a time; - * attempting to start a second asynchronous operation while the first one - * has not yet completed will result in an exception being thrown. - * - * @author Bruno Oliveira (Google) - */ -public class IabHelper { - // Billing response codes - public static final int BILLING_RESPONSE_RESULT_OK = 0; - public static final int BILLING_RESPONSE_RESULT_USER_CANCELED = 1; - public static final int BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE = 3; - public static final int BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE = 4; - public static final int BILLING_RESPONSE_RESULT_DEVELOPER_ERROR = 5; - public static final int BILLING_RESPONSE_RESULT_ERROR = 6; - public static final int BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED = 7; - public static final int BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED = 8; - // IAB Helper error codes - public static final int IABHELPER_ERROR_BASE = -1000; - public static final int IABHELPER_REMOTE_EXCEPTION = -1001; - public static final int IABHELPER_BAD_RESPONSE = -1002; - public static final int IABHELPER_VERIFICATION_FAILED = -1003; - public static final int IABHELPER_SEND_INTENT_FAILED = -1004; - public static final int IABHELPER_USER_CANCELLED = -1005; - public static final int IABHELPER_UNKNOWN_PURCHASE_RESPONSE = -1006; - public static final int IABHELPER_MISSING_TOKEN = -1007; - public static final int IABHELPER_UNKNOWN_ERROR = -1008; - public static final int IABHELPER_SUBSCRIPTIONS_NOT_AVAILABLE = -1009; - public static final int IABHELPER_INVALID_CONSUMPTION = -1010; - // Keys for the responses from InAppBillingService - public static final String RESPONSE_CODE = "RESPONSE_CODE"; - public static final String RESPONSE_GET_SKU_DETAILS_LIST = "DETAILS_LIST"; - public static final String RESPONSE_BUY_INTENT = "BUY_INTENT"; - public static final String RESPONSE_INAPP_PURCHASE_DATA = "INAPP_PURCHASE_DATA"; - public static final String RESPONSE_INAPP_SIGNATURE = "INAPP_DATA_SIGNATURE"; - public static final String RESPONSE_INAPP_ITEM_LIST = "INAPP_PURCHASE_ITEM_LIST"; - public static final String RESPONSE_INAPP_PURCHASE_DATA_LIST = "INAPP_PURCHASE_DATA_LIST"; - public static final String RESPONSE_INAPP_SIGNATURE_LIST = "INAPP_DATA_SIGNATURE_LIST"; - public static final String INAPP_CONTINUATION_TOKEN = "INAPP_CONTINUATION_TOKEN"; - // Item types - public static final String ITEM_TYPE_INAPP = "inapp"; - public static final String ITEM_TYPE_SUBS = "subs"; - // some fields on the getSkuDetails response bundle - public static final String GET_SKU_DETAILS_ITEM_LIST = "ITEM_ID_LIST"; - public static final String GET_SKU_DETAILS_ITEM_TYPE_LIST = "ITEM_TYPE_LIST"; - // Is debug logging enabled? - boolean mDebugLog = false; - String mDebugTag = "IabHelper"; - // Is setup done? - boolean mSetupDone = false; - // Has this object been disposed of? (If so, we should ignore callbacks, etc) - boolean mDisposed = false; - boolean mIsBound = false; - // Are subscriptions supported? - boolean mSubscriptionsSupported = false; - // Is an asynchronous operation in progress? - // (only one at a time can be in progress) - boolean mAsyncInProgress = false; - // (for logging/debugging) - // if mAsyncInProgress == true, what asynchronous operation is in progress? - String mAsyncOperation = ""; - // Context we were passed during initialization - Context mContext; - // Connection to the service - IInAppBillingService mService; - ServiceConnection mServiceConn; - // The request code used to launch purchase flow - int mRequestCode; - // The item type of the current purchase flow - String mPurchasingItemType; - // Public key for verifying signature, in base64 encoding - String mSignatureBase64 = null; - // The listener registered on launchPurchaseFlow, which we have to call back when - // the purchase finishes - OnIabPurchaseFinishedListener mPurchaseListener; - - /** - * Creates an instance. After creation, it will not yet be ready to use. You must perform - * setup by calling {@link #startSetup} and wait for setup to complete. This constructor does not - * block and is safe to call from a UI thread. - * - * @param ctx Your application or Activity context. Needed to bind to the in-app billing service. - * @param base64PublicKey Your application's public key, encoded in base64. - * This is used for verification of purchase signatures. You can find your app's base64-encoded - * public key in your application's page on Google Play Developer Console. Note that this - * is NOT your "developer public key". - */ - public IabHelper(Context ctx, String base64PublicKey) { - mContext = ctx.getApplicationContext(); - mSignatureBase64 = base64PublicKey; - logDebug("IAB helper created."); - } - - /** - * Returns a human-readable description for the given response code. - * - * @param code The response code - * @return A human-readable string explaining the result code. - * It also includes the result code numerically. - */ - public static String getResponseDesc(int code) { - String[] iab_msgs = ("0:OK/1:User Canceled/2:Unknown/" + - "3:Billing Unavailable/4:Item unavailable/" + - "5:Developer Error/6:Error/7:Item Already Owned/" + - "8:Item not owned").split("/"); - String[] iabhelper_msgs = ("0:OK/-1001:Remote exception during initialization/" + - "-1002:Bad response received/" + - "-1003:Purchase signature verification failed/" + - "-1004:Send intent failed/" + - "-1005:User cancelled/" + - "-1006:Unknown purchase response/" + - "-1007:Missing token/" + - "-1008:Unknown error/" + - "-1009:Subscriptions not available/" + - "-1010:Invalid consumption attempt").split("/"); - - if (code <= IABHELPER_ERROR_BASE) { - int index = IABHELPER_ERROR_BASE - code; - if (index >= 0 && index < iabhelper_msgs.length) return iabhelper_msgs[index]; - else return String.valueOf(code) + ":Unknown IAB Helper Error"; - } else if (code < 0 || code >= iab_msgs.length) - return String.valueOf(code) + ":Unknown"; - else - return iab_msgs[code]; - } - - /** - * Enables or disable debug logging through LogCat. - */ - public void enableDebugLogging(boolean enable, String tag) { - checkNotDisposed(); - mDebugLog = enable; - mDebugTag = tag; - } - - public void enableDebugLogging(boolean enable) { - checkNotDisposed(); - mDebugLog = enable; - } - - /** - * Starts the setup process. This will start up the setup process asynchronously. - * You will be notified through the listener when the setup process is complete. - * This method is safe to call from a UI thread. - * - * @param listener The listener to notify when the setup process is complete. - */ - public void startSetup(final OnIabSetupFinishedListener listener) { - // If already set up, can't do it again. - checkNotDisposed(); - if (mSetupDone) throw new IllegalStateException("IAB helper is already set up."); - - // Connection to IAB service - logDebug("Starting in-app billing setup."); - mServiceConn = new ServiceConnection() { - @Override - public void onServiceDisconnected(ComponentName name) { - logDebug("Billing service disconnected."); - mService = null; - } - - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - if (mDisposed) return; - logDebug("Billing service connected."); - mService = IInAppBillingService.Stub.asInterface(service); - String packageName = mContext.getPackageName(); - try { - logDebug("Checking for in-app billing 3 support."); - - // check for in-app billing v3 support - int response = mService.isBillingSupported(3, packageName, ITEM_TYPE_INAPP); - if (response != BILLING_RESPONSE_RESULT_OK) { - if (listener != null) listener.onIabSetupFinished(new IabResult(response, - "Error checking for billing v3 support.")); - - // if in-app purchases aren't supported, neither are subscriptions. - mSubscriptionsSupported = false; - return; - } - logDebug("In-app billing version 3 supported for " + packageName); - - // check for v3 subscriptions support - response = mService.isBillingSupported(3, packageName, ITEM_TYPE_SUBS); - if (response == BILLING_RESPONSE_RESULT_OK) { - logDebug("Subscriptions AVAILABLE."); - mSubscriptionsSupported = true; - } else { - logDebug("Subscriptions NOT AVAILABLE. Response: " + response); - } - - mSetupDone = true; - } catch (RemoteException e) { - if (listener != null) { - listener.onIabSetupFinished(new IabResult(IABHELPER_REMOTE_EXCEPTION, - "RemoteException while setting up in-app billing.")); - } - e.printStackTrace(); - return; - } - - if (listener != null) { - listener.onIabSetupFinished(new IabResult(BILLING_RESPONSE_RESULT_OK, "Setup successful.")); - } - } - }; - - Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND"); - serviceIntent.setPackage("com.android.vending"); - List ri = mContext.getPackageManager().queryIntentServices(serviceIntent, 0); - if (ri != null && !ri.isEmpty()) { - // service available to handle that Intent - mIsBound = mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE); - } else { - // no service available to handle that Intent - if (listener != null) { - listener.onIabSetupFinished( - new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE, - "Billing service unavailable on device.") - ); - } - } - } - - /** - * Dispose of object, releasing resources. It's very important to call this - * method when you are done with this object. It will release any resources - * used by it such as service connections. Naturally, once the object is - * disposed of, it can't be used again. - */ - public void dispose() { - logDebug("Disposing."); - mSetupDone = false; - if (mServiceConn != null) { - logDebug("Unbinding from service."); - if (mContext != null && mIsBound) { - mContext.unbindService(mServiceConn); - } - } - mDisposed = true; - mContext = null; - mServiceConn = null; - mService = null; - mPurchaseListener = null; - } - - private void checkNotDisposed() { - if (mDisposed) - throw new IllegalStateException("IabHelper was disposed of, so it cannot be used."); - } - - /** - * Returns whether subscriptions are supported. - */ - public boolean subscriptionsSupported() { - checkNotDisposed(); - return mSubscriptionsSupported; - } - - public void launchPurchaseFlow(Activity act, String sku, int requestCode, OnIabPurchaseFinishedListener listener) { - launchPurchaseFlow(act, sku, requestCode, listener, ""); - } - - public void launchPurchaseFlow(Activity act, String sku, int requestCode, - OnIabPurchaseFinishedListener listener, String extraData) { - launchPurchaseFlow(act, sku, ITEM_TYPE_INAPP, requestCode, listener, extraData); - } - - public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode, - OnIabPurchaseFinishedListener listener) { - launchSubscriptionPurchaseFlow(act, sku, requestCode, listener, ""); - } - - public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode, - OnIabPurchaseFinishedListener listener, String extraData) { - launchPurchaseFlow(act, sku, ITEM_TYPE_SUBS, requestCode, listener, extraData); - } - - /** - * Initiate the UI flow for an in-app purchase. Call this method to initiate an in-app purchase, - * which will involve bringing up the Google Play screen. The calling activity will be paused while - * the user interacts with Google Play, and the result will be delivered via the activity's - * {@link android.app.Activity#onActivityResult} method, at which point you must call - * this object's {@link #handleActivityResult} method to continue the purchase flow. This method - * MUST be called from the UI thread of the Activity. - * - * @param act The calling activity. - * @param sku The sku of the item to purchase. - * @param itemType indicates if it's a product or a subscription (ITEM_TYPE_INAPP or ITEM_TYPE_SUBS) - * @param requestCode A request code (to differentiate from other responses -- - * as in {@link android.app.Activity#startActivityForResult}). - * @param listener The listener to notify when the purchase process finishes - * @param extraData Extra data (developer payload), which will be returned with the purchase data - * when the purchase completes. This extra data will be permanently bound to that purchase - * and will always be returned when the purchase is queried. - */ - public void launchPurchaseFlow(Activity act, String sku, String itemType, int requestCode, - OnIabPurchaseFinishedListener listener, String extraData) { - checkNotDisposed(); - checkSetupDone("launchPurchaseFlow"); - flagStartAsync("launchPurchaseFlow"); - IabResult result; - - if (itemType.equals(ITEM_TYPE_SUBS) && !mSubscriptionsSupported) { - IabResult r = new IabResult(IABHELPER_SUBSCRIPTIONS_NOT_AVAILABLE, - "Subscriptions are not available."); - flagEndAsync(); - if (listener != null) listener.onIabPurchaseFinished(r, null); - return; - } - - try { - logDebug("Constructing buy intent for " + sku + ", item type: " + itemType); - Bundle buyIntentBundle = mService.getBuyIntent(3, mContext.getPackageName(), sku, itemType, extraData); - int response = getResponseCodeFromBundle(buyIntentBundle); - if (response != BILLING_RESPONSE_RESULT_OK) { - logError("Unable to buy item, Error response: " + getResponseDesc(response)); - flagEndAsync(); - result = new IabResult(response, "Unable to buy item"); - if (listener != null) listener.onIabPurchaseFinished(result, null); - return; - } - - PendingIntent pendingIntent = buyIntentBundle.getParcelable(RESPONSE_BUY_INTENT); - logDebug("Launching buy intent for " + sku + ". Request code: " + requestCode); - mRequestCode = requestCode; - mPurchaseListener = listener; - mPurchasingItemType = itemType; - act.startIntentSenderForResult(pendingIntent.getIntentSender(), - requestCode, new Intent(), - 0, 0, - 0); - } catch (SendIntentException e) { - logError("SendIntentException while launching purchase flow for sku " + sku); - e.printStackTrace(); - flagEndAsync(); - - result = new IabResult(IABHELPER_SEND_INTENT_FAILED, "Failed to send intent."); - if (listener != null) listener.onIabPurchaseFinished(result, null); - } catch (RemoteException e) { - logError("RemoteException while launching purchase flow for sku " + sku); - e.printStackTrace(); - flagEndAsync(); - - result = new IabResult(IABHELPER_REMOTE_EXCEPTION, "Remote exception while starting purchase flow"); - if (listener != null) listener.onIabPurchaseFinished(result, null); - } - } - - /** - * Handles an activity result that's part of the purchase flow in in-app billing. If you - * are calling {@link #launchPurchaseFlow}, then you must call this method from your - * Activity's {@link android.app.Activity@onActivityResult} method. This method - * MUST be called from the UI thread of the Activity. - * - * @param requestCode The requestCode as you received it. - * @param resultCode The resultCode as you received it. - * @param data The data (Intent) as you received it. - * @return Returns true if the result was related to a purchase flow and was handled; - * false if the result was not related to a purchase, in which case you should - * handle it normally. - */ - public boolean handleActivityResult(int requestCode, int resultCode, Intent data) { - IabResult result; - if (requestCode != mRequestCode) return false; - - checkNotDisposed(); - checkSetupDone("handleActivityResult"); - - // end of async purchase operation that started on launchPurchaseFlow - flagEndAsync(); - - if (data == null) { - logError("Null data in IAB activity result."); - result = new IabResult(IABHELPER_BAD_RESPONSE, "Null data in IAB result"); - if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null); - return true; - } - - int responseCode = getResponseCodeFromIntent(data); - String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA); - String dataSignature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE); - - if (resultCode == Activity.RESULT_OK && responseCode == BILLING_RESPONSE_RESULT_OK) { - logDebug("Successful resultcode from purchase activity."); - logDebug("Purchase data: " + purchaseData); - logDebug("Data signature: " + dataSignature); - logDebug("Extras: " + data.getExtras()); - logDebug("Expected item type: " + mPurchasingItemType); - - if (purchaseData == null || dataSignature == null) { - logError("BUG: either purchaseData or dataSignature is null."); - logDebug("Extras: " + data.getExtras().toString()); - result = new IabResult(IABHELPER_UNKNOWN_ERROR, "IAB returned null purchaseData or dataSignature"); - if (mPurchaseListener != null) - mPurchaseListener.onIabPurchaseFinished(result, null); - return true; - } - - @SuppressWarnings("UnusedAssignment") Purchase purchase = null; - try { - purchase = new Purchase(mPurchasingItemType, purchaseData, dataSignature); - String sku = purchase.getSku(); - - // Verify signature - if (!Security.verifyPurchase(mSignatureBase64, purchaseData, dataSignature)) { - logError("Purchase signature verification FAILED for sku " + sku); - result = new IabResult(IABHELPER_VERIFICATION_FAILED, "Signature verification failed for sku " + sku); - if (mPurchaseListener != null) - mPurchaseListener.onIabPurchaseFinished(result, purchase); - return true; - } - logDebug("Purchase signature successfully verified."); - } catch (JSONException e) { - logError("Failed to parse purchase data."); - e.printStackTrace(); - result = new IabResult(IABHELPER_BAD_RESPONSE, "Failed to parse purchase data."); - if (mPurchaseListener != null) - mPurchaseListener.onIabPurchaseFinished(result, null); - return true; - } - - if (mPurchaseListener != null) { - mPurchaseListener.onIabPurchaseFinished(new IabResult(BILLING_RESPONSE_RESULT_OK, "Success"), purchase); - } - } else if (resultCode == Activity.RESULT_OK) { - // result code was OK, but in-app billing response was not OK. - logDebug("Result code was OK but in-app billing response was not OK: " + getResponseDesc(responseCode)); - if (mPurchaseListener != null) { - result = new IabResult(responseCode, "Problem purchashing item."); - mPurchaseListener.onIabPurchaseFinished(result, null); - } - } else if (resultCode == Activity.RESULT_CANCELED) { - logDebug("Purchase canceled - Response: " + getResponseDesc(responseCode)); - result = new IabResult(IABHELPER_USER_CANCELLED, "User canceled."); - if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null); - } else { - logError("Purchase failed. Result code: " + Integer.toString(resultCode) - + ". Response: " + getResponseDesc(responseCode)); - result = new IabResult(IABHELPER_UNKNOWN_PURCHASE_RESPONSE, "Unknown purchase response."); - if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null); - } - return true; - } - - public Inventory queryInventory(boolean querySkuDetails, List moreSkus) throws IabException { - return queryInventory(querySkuDetails, moreSkus, null); - } - - /** - * Queries the inventory. This will query all owned items from the server, as well as - * information on additional skus, if specified. This method may block or take long to execute. - * Do not call from a UI thread. For that, use the non-blocking version {@link #refreshInventoryAsync}. - * - * @param querySkuDetails if true, SKU details (price, description, etc) will be queried as well - * as purchase information. - * @param moreItemSkus additional PRODUCT skus to query information on, regardless of ownership. - * Ignored if null or if querySkuDetails is false. - * @param moreSubsSkus additional SUBSCRIPTIONS skus to query information on, regardless of ownership. - * Ignored if null or if querySkuDetails is false. - * @throws IabException if a problem occurs while refreshing the inventory. - */ - public Inventory queryInventory(boolean querySkuDetails, List moreItemSkus, - List moreSubsSkus) throws IabException { - checkNotDisposed(); - checkSetupDone("queryInventory"); - try { - Inventory inv = new Inventory(); - int r = queryPurchases(inv, ITEM_TYPE_INAPP); - if (r != BILLING_RESPONSE_RESULT_OK) { - throw new IabException(r, "Error refreshing inventory (querying owned items)."); - } - - if (querySkuDetails) { - r = querySkuDetails(ITEM_TYPE_INAPP, inv, moreItemSkus); - if (r != BILLING_RESPONSE_RESULT_OK) { - throw new IabException(r, "Error refreshing inventory (querying prices of items)."); - } - } - - // if subscriptions are supported, then also query for subscriptions - if (mSubscriptionsSupported) { - r = queryPurchases(inv, ITEM_TYPE_SUBS); - if (r != BILLING_RESPONSE_RESULT_OK) { - throw new IabException(r, "Error refreshing inventory (querying owned subscriptions)."); - } - - if (querySkuDetails) { - r = querySkuDetails(ITEM_TYPE_SUBS, inv, moreItemSkus); - if (r != BILLING_RESPONSE_RESULT_OK) { - throw new IabException(r, "Error refreshing inventory (querying prices of subscriptions)."); - } - } - } - - return inv; - } catch (RemoteException e) { - throw new IabException(IABHELPER_REMOTE_EXCEPTION, "Remote exception while refreshing inventory.", e); - } catch (JSONException e) { - throw new IabException(IABHELPER_BAD_RESPONSE, "Error parsing JSON response while refreshing inventory.", e); - } - } - - /** - * Asynchronous wrapper for inventory query. This will perform an inventory - * query as described in {@link #queryInventory}, but will do so asynchronously - * and call back the specified listener upon completion. This method is safe to - * call from a UI thread. - * - * @param querySkuDetails as in {@link #queryInventory} - * @param moreSkus as in {@link #queryInventory} - * @param listener The listener to notify when the refresh operation completes. - */ - public void queryInventoryAsync(final boolean querySkuDetails, - final List moreSkus, - final QueryInventoryFinishedListener listener) { - final Handler handler = new Handler(); - checkNotDisposed(); - checkSetupDone("queryInventory"); - flagStartAsync("refresh inventory"); - (new Thread(new Runnable() { - public void run() { - IabResult result = new IabResult(BILLING_RESPONSE_RESULT_OK, "Inventory refresh successful."); - Inventory inv = null; - try { - inv = queryInventory(querySkuDetails, moreSkus); - } catch (IabException ex) { - result = ex.getResult(); - } - - flagEndAsync(); - - final IabResult result_f = result; - final Inventory inv_f = inv; - if (!mDisposed && listener != null) { - handler.post(new Runnable() { - public void run() { - listener.onQueryInventoryFinished(result_f, inv_f); - } - }); - } - } - })).start(); - } - - public void queryInventoryAsync(QueryInventoryFinishedListener listener) { - queryInventoryAsync(true, null, listener); - } - - public void queryInventoryAsync(boolean querySkuDetails, QueryInventoryFinishedListener listener) { - queryInventoryAsync(querySkuDetails, null, listener); - } - - /** - * Consumes a given in-app product. Consuming can only be done on an item - * that's owned, and as a result of consumption, the user will no longer own it. - * This method may block or take long to return. Do not call from the UI thread. - * For that, see {@link #consumeAsync}. - * - * @param itemInfo The PurchaseInfo that represents the item to consume. - * @throws IabException if there is a problem during consumption. - */ - void consume(Purchase itemInfo) throws IabException { - checkNotDisposed(); - checkSetupDone("consume"); - - if (!itemInfo.mItemType.equals(ITEM_TYPE_INAPP)) { - throw new IabException(IABHELPER_INVALID_CONSUMPTION, - "Items of type '" + itemInfo.mItemType + "' can't be consumed."); - } - - try { - String token = itemInfo.getToken(); - String sku = itemInfo.getSku(); - if (token == null || token.equals("")) { - logError("Can't consume " + sku + ". No token."); - throw new IabException(IABHELPER_MISSING_TOKEN, "PurchaseInfo is missing token for sku: " - + sku + " " + itemInfo); - } - - logDebug("Consuming sku: " + sku + ", token: " + token); - int response = mService.consumePurchase(3, mContext.getPackageName(), token); - if (response == BILLING_RESPONSE_RESULT_OK) { - logDebug("Successfully consumed sku: " + sku); - } else { - logDebug("Error consuming consuming sku " + sku + ". " + getResponseDesc(response)); - throw new IabException(response, "Error consuming sku " + sku); - } - } catch (RemoteException e) { - throw new IabException(IABHELPER_REMOTE_EXCEPTION, "Remote exception while consuming. PurchaseInfo: " + itemInfo, e); - } - } - - /** - * Asynchronous wrapper to item consumption. Works like {@link #consume}, but - * performs the consumption in the background and notifies completion through - * the provided listener. This method is safe to call from a UI thread. - * - * @param purchase The purchase to be consumed. - * @param listener The listener to notify when the consumption operation finishes. - */ - public void consumeAsync(Purchase purchase, OnConsumeFinishedListener listener) { - checkNotDisposed(); - checkSetupDone("consume"); - List purchases = new ArrayList<>(); - purchases.add(purchase); - consumeAsyncInternal(purchases, listener, null); - } - - /** - * Same as {@link consumeAsync}, but for multiple items at once. - * - * @param purchases The list of PurchaseInfo objects representing the purchases to consume. - * @param listener The listener to notify when the consumption operation finishes. - */ - public void consumeAsync(List purchases, OnConsumeMultiFinishedListener listener) { - checkNotDisposed(); - checkSetupDone("consume"); - consumeAsyncInternal(purchases, null, listener); - } - - // Checks that setup was done; if not, throws an exception. - void checkSetupDone(String operation) { - if (!mSetupDone) { - logError("Illegal state for operation (" + operation + "): IAB helper is not set up."); - throw new IllegalStateException("IAB helper is not set up. Can't perform operation: " + operation); - } - } - - // Workaround to bug where sometimes response codes come as Long instead of Integer - int getResponseCodeFromBundle(Bundle b) { - Object o = b.get(RESPONSE_CODE); - if (o == null) { - logDebug("Bundle with null response code, assuming OK (known issue)"); - return BILLING_RESPONSE_RESULT_OK; - } else if (o instanceof Integer) return (Integer) o; - else if (o instanceof Long) return (int) ((Long) o).longValue(); - else { - logError("Unexpected type for bundle response code."); - logError(o.getClass().getName()); - throw new RuntimeException("Unexpected type for bundle response code: " + o.getClass().getName()); - } - } - - // Workaround to bug where sometimes response codes come as Long instead of Integer - int getResponseCodeFromIntent(Intent i) { - Object o = i.getExtras().get(RESPONSE_CODE); - if (o == null) { - logError("Intent with no response code, assuming OK (known issue)"); - return BILLING_RESPONSE_RESULT_OK; - } else if (o instanceof Integer) return (Integer) o; - else if (o instanceof Long) return (int) ((Long) o).longValue(); - else { - logError("Unexpected type for intent response code."); - logError(o.getClass().getName()); - throw new RuntimeException("Unexpected type for intent response code: " + o.getClass().getName()); - } - } - - void flagStartAsync(String operation) { - if (mAsyncInProgress) throw new IllegalStateException("Can't start async operation (" + - operation + ") because another async operation(" + mAsyncOperation + ") is in progress."); - mAsyncOperation = operation; - mAsyncInProgress = true; - logDebug("Starting async operation: " + operation); - } - - void flagEndAsync() { - logDebug("Ending async operation: " + mAsyncOperation); - mAsyncOperation = ""; - mAsyncInProgress = false; - } - - int queryPurchases(Inventory inv, String itemType) throws JSONException, RemoteException { - // Query purchases - logDebug("Querying owned items, item type: " + itemType); - logDebug("Package name: " + mContext.getPackageName()); - boolean verificationFailed = false; - String continueToken = null; - - do { - logDebug("Calling getPurchases with continuation token: " + continueToken); - Bundle ownedItems = mService.getPurchases(3, mContext.getPackageName(), - itemType, continueToken); - - int response = getResponseCodeFromBundle(ownedItems); - logDebug("Owned items response: " + String.valueOf(response)); - if (response != BILLING_RESPONSE_RESULT_OK) { - logDebug("getPurchases() failed: " + getResponseDesc(response)); - return response; - } - if (!ownedItems.containsKey(RESPONSE_INAPP_ITEM_LIST) - || !ownedItems.containsKey(RESPONSE_INAPP_PURCHASE_DATA_LIST) - || !ownedItems.containsKey(RESPONSE_INAPP_SIGNATURE_LIST)) { - logError("Bundle returned from getPurchases() doesn't contain required fields."); - return IABHELPER_BAD_RESPONSE; - } - - ArrayList ownedSkus = ownedItems.getStringArrayList( - RESPONSE_INAPP_ITEM_LIST); - ArrayList purchaseDataList = ownedItems.getStringArrayList( - RESPONSE_INAPP_PURCHASE_DATA_LIST); - ArrayList signatureList = ownedItems.getStringArrayList( - RESPONSE_INAPP_SIGNATURE_LIST); - - for (int i = 0; i < purchaseDataList.size(); ++i) { - String purchaseData = purchaseDataList.get(i); - String signature = signatureList.get(i); - String sku = ownedSkus.get(i); - if (Security.verifyPurchase(mSignatureBase64, purchaseData, signature)) { - logDebug("Sku is owned: " + sku); - Purchase purchase = new Purchase(itemType, purchaseData, signature); - - if (TextUtils.isEmpty(purchase.getToken())) { - logWarn("BUG: empty/null token!"); - logDebug("Purchase data: " + purchaseData); - } - - // Record ownership and token - inv.addPurchase(purchase); - } else { - logWarn("Purchase signature verification **FAILED**. Not adding item."); - logDebug(" Purchase data: " + purchaseData); - logDebug(" Signature: " + signature); - verificationFailed = true; - } - } - - continueToken = ownedItems.getString(INAPP_CONTINUATION_TOKEN); - logDebug("Continuation token: " + continueToken); - } while (!TextUtils.isEmpty(continueToken)); - - return verificationFailed ? IABHELPER_VERIFICATION_FAILED : BILLING_RESPONSE_RESULT_OK; - } - - int querySkuDetails(String itemType, Inventory inv, List moreSkus) - throws RemoteException, JSONException { - logDebug("Querying SKU details."); - ArrayList skuList = new ArrayList<>(); - skuList.addAll(inv.getAllOwnedSkus(itemType)); - if (moreSkus != null) { - for (String sku : moreSkus) { - if (!skuList.contains(sku)) { - skuList.add(sku); - } - } - } - - if (skuList.size() == 0) { - logDebug("queryPrices: nothing to do because there are no SKUs."); - return BILLING_RESPONSE_RESULT_OK; - } - - Bundle querySkus = new Bundle(); - querySkus.putStringArrayList(GET_SKU_DETAILS_ITEM_LIST, skuList); - Bundle skuDetails = mService.getSkuDetails(3, mContext.getPackageName(), - itemType, querySkus); - - if (!skuDetails.containsKey(RESPONSE_GET_SKU_DETAILS_LIST)) { - int response = getResponseCodeFromBundle(skuDetails); - if (response != BILLING_RESPONSE_RESULT_OK) { - logDebug("getSkuDetails() failed: " + getResponseDesc(response)); - return response; - } else { - logError("getSkuDetails() returned a bundle with neither an error nor a detail list."); - return IABHELPER_BAD_RESPONSE; - } - } - - ArrayList responseList = skuDetails.getStringArrayList( - RESPONSE_GET_SKU_DETAILS_LIST); - - for (String thisResponse : responseList) { - SkuDetails d = new SkuDetails(itemType, thisResponse); - logDebug("Got sku details: " + d); - inv.addSkuDetails(d); - } - return BILLING_RESPONSE_RESULT_OK; - } - - void consumeAsyncInternal(final List purchases, - final OnConsumeFinishedListener singleListener, - final OnConsumeMultiFinishedListener multiListener) { - final Handler handler = new Handler(); - flagStartAsync("consume"); - (new Thread(new Runnable() { - public void run() { - final List results = new ArrayList<>(); - for (Purchase purchase : purchases) { - try { - consume(purchase); - results.add(new IabResult(BILLING_RESPONSE_RESULT_OK, "Successful consume of sku " + purchase.getSku())); - } catch (IabException ex) { - results.add(ex.getResult()); - } - } - - flagEndAsync(); - if (!mDisposed && singleListener != null) { - handler.post(new Runnable() { - public void run() { - singleListener.onConsumeFinished(purchases.get(0), results.get(0)); - } - }); - } - if (!mDisposed && multiListener != null) { - handler.post(new Runnable() { - public void run() { - multiListener.onConsumeMultiFinished(purchases, results); - } - }); - } - } - })).start(); - } - - void logDebug(String msg) { - if (mDebugLog) Log.d(mDebugTag, msg); - } - - void logError(String msg) { - Log.e(mDebugTag, "In-app billing error: " + msg); - } - - void logWarn(String msg) { - Log.w(mDebugTag, "In-app billing warning: " + msg); - } - - /** - * Callback for setup process. This listener's {@link #onIabSetupFinished} method is called - * when the setup process is complete. - */ - public interface OnIabSetupFinishedListener { - /** - * Called to notify that setup is complete. - * - * @param result The result of the setup process. - */ - public void onIabSetupFinished(IabResult result); - } - - - /** - * Callback that notifies when a purchase is finished. - */ - public interface OnIabPurchaseFinishedListener { - /** - * Called to notify that an in-app purchase finished. If the purchase was successful, - * then the sku parameter specifies which item was purchased. If the purchase failed, - * the sku and extraData parameters may or may not be null, depending on how far the purchase - * process went. - * - * @param result The result of the purchase. - * @param info The purchase information (null if purchase failed) - */ - public void onIabPurchaseFinished(IabResult result, Purchase info); - } - - /** - * Listener that notifies when an inventory query operation completes. - */ - public interface QueryInventoryFinishedListener { - /** - * Called to notify that an inventory query operation completed. - * - * @param result The result of the operation. - * @param inv The inventory. - */ - public void onQueryInventoryFinished(IabResult result, Inventory inv); - } - - /** - * Callback that notifies when a consumption operation finishes. - */ - public interface OnConsumeFinishedListener { - /** - * Called to notify that a consumption has finished. - * - * @param purchase The purchase that was (or was to be) consumed. - * @param result The result of the consumption operation. - */ - public void onConsumeFinished(Purchase purchase, IabResult result); - } - - /** - * Callback that notifies when a multi-item consumption operation finishes. - */ - public interface OnConsumeMultiFinishedListener { - /** - * Called to notify that a consumption of multiple items has finished. - * - * @param purchases The purchases that were (or were to be) consumed. - * @param results The results of each consumption operation, corresponding to each - * sku. - */ - public void onConsumeMultiFinished(List purchases, List results); - } -} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/IabResult.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/IabResult.java deleted file mode 100644 index c01c194..0000000 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/IabResult.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Turbo Editor is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package sharedcode.turboeditor.iab.utils; - -/** - * Represents the result of an in-app billing operation. - * A result is composed of a response code (an integer) and possibly a - * message (String). You can get those by calling - * {@link #getResponse} and {@link #getMessage()}, respectively. You - * can also inquire whether a result is a success or a failure by - * calling {@link #isSuccess()} and {@link #isFailure()}. - */ -public class IabResult { - int mResponse; - String mMessage; - - public IabResult(int response, String message) { - mResponse = response; - if (message == null || message.trim().length() == 0) { - mMessage = IabHelper.getResponseDesc(response); - } else { - mMessage = message + " (response: " + IabHelper.getResponseDesc(response) + ")"; - } - } - - public int getResponse() { - return mResponse; - } - - public String getMessage() { - return mMessage; - } - - public boolean isSuccess() { - return mResponse == IabHelper.BILLING_RESPONSE_RESULT_OK; - } - - public boolean isFailure() { - return !isSuccess(); - } - - public String toString() { - return "IabResult: " + getMessage(); - } -} - diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Inventory.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Inventory.java deleted file mode 100644 index c3b3b23..0000000 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Inventory.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Turbo Editor is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package sharedcode.turboeditor.iab.utils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Represents a block of information about in-app items. - * An Inventory is returned by such methods as {@link IabHelper#queryInventory}. - */ -public class Inventory { - Map mSkuMap = new HashMap<>(); - Map mPurchaseMap = new HashMap<>(); - - Inventory() { - } - - /** - * Returns the listing details for an in-app product. - */ - public SkuDetails getSkuDetails(String sku) { - return mSkuMap.get(sku); - } - - /** - * Returns purchase information for a given product, or null if there is no purchase. - */ - public Purchase getPurchase(String sku) { - return mPurchaseMap.get(sku); - } - - /** - * Returns whether or not there exists a purchase of the given product. - */ - public boolean hasPurchase(String sku) { - return mPurchaseMap.containsKey(sku); - } - - /** - * Return whether or not details about the given product are available. - */ - public boolean hasDetails(String sku) { - return mSkuMap.containsKey(sku); - } - - /** - * Erase a purchase (locally) from the inventory, given its product ID. This just - * modifies the Inventory object locally and has no effect on the server! This is - * useful when you have an existing Inventory object which you know to be up to date, - * and you have just consumed an item successfully, which means that erasing its - * purchase data from the Inventory you already have is quicker than querying for - * a new Inventory. - */ - public void erasePurchase(String sku) { - if (mPurchaseMap.containsKey(sku)) mPurchaseMap.remove(sku); - } - - /** - * Returns a list of all owned product IDs. - */ - List getAllOwnedSkus() { - return new ArrayList<>(mPurchaseMap.keySet()); - } - - /** - * Returns a list of all owned product IDs of a given type - */ - List getAllOwnedSkus(String itemType) { - List result = new ArrayList<>(); - for (Purchase p : mPurchaseMap.values()) { - if (p.getItemType().equals(itemType)) result.add(p.getSku()); - } - return result; - } - - /** - * Returns a list of all purchases. - */ - List getAllPurchases() { - return new ArrayList<>(mPurchaseMap.values()); - } - - void addSkuDetails(SkuDetails d) { - mSkuMap.put(d.getSku(), d); - } - - void addPurchase(Purchase p) { - mPurchaseMap.put(p.getSku(), p); - } -} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Purchase.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Purchase.java deleted file mode 100644 index d63575b..0000000 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Purchase.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Turbo Editor is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package sharedcode.turboeditor.iab.utils; - -import org.json.JSONException; -import org.json.JSONObject; - -/** - * Represents an in-app billing purchase. - */ -public class Purchase { - String mItemType; // ITEM_TYPE_INAPP or ITEM_TYPE_SUBS - String mOrderId; - String mPackageName; - String mSku; - long mPurchaseTime; - int mPurchaseState; - String mDeveloperPayload; - String mToken; - String mOriginalJson; - String mSignature; - - public Purchase(String itemType, String jsonPurchaseInfo, String signature) throws JSONException { - mItemType = itemType; - mOriginalJson = jsonPurchaseInfo; - JSONObject o = new JSONObject(mOriginalJson); - mOrderId = o.optString("orderId"); - mPackageName = o.optString("packageName"); - mSku = o.optString("productId"); - mPurchaseTime = o.optLong("purchaseTime"); - mPurchaseState = o.optInt("purchaseState"); - mDeveloperPayload = o.optString("developerPayload"); - mToken = o.optString("token", o.optString("purchaseToken")); - mSignature = signature; - } - - public String getItemType() { - return mItemType; - } - - public String getOrderId() { - return mOrderId; - } - - public String getPackageName() { - return mPackageName; - } - - public String getSku() { - return mSku; - } - - public long getPurchaseTime() { - return mPurchaseTime; - } - - public int getPurchaseState() { - return mPurchaseState; - } - - public String getDeveloperPayload() { - return mDeveloperPayload; - } - - public String getToken() { - return mToken; - } - - public String getOriginalJson() { - return mOriginalJson; - } - - public String getSignature() { - return mSignature; - } - - @Override - public String toString() { - return "PurchaseInfo(type:" + mItemType + "):" + mOriginalJson; - } -} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Security.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Security.java deleted file mode 100644 index adaed71..0000000 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Security.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Turbo Editor is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package sharedcode.turboeditor.iab.utils; - -import android.text.TextUtils; -import android.util.Log; - -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.PublicKey; -import java.security.Signature; -import java.security.SignatureException; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.X509EncodedKeySpec; - -/** - * Security-related methods. For a secure implementation, all of this code - * should be implemented on a server that communicates with the - * application on the device. For the sake of simplicity and clarity of this - * example, this code is included here and is executed on the device. If you - * must verify the purchases on the phone, you should obfuscate this code to - * make it harder for an attacker to replace the code with stubs that treat all - * purchases as verified. - */ -public class Security { - private static final String TAG = "IABUtil/Security"; - - private static final String KEY_FACTORY_ALGORITHM = "RSA"; - private static final String SIGNATURE_ALGORITHM = "SHA1withRSA"; - - /** - * Verifies that the data was signed with the given signature, and returns - * the verified purchase. The data is in JSON format and signed - * with a private key. The data also contains the {@link PurchaseState} - * and product ID of the purchase. - * - * @param base64PublicKey the base64-encoded public key to use for verifying. - * @param signedData the signed JSON string (signed, not encrypted) - * @param signature the signature for the data, signed with the private key - */ - public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) { - if (TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey) || - TextUtils.isEmpty(signature)) { - Log.e(TAG, "Purchase verification failed: missing data."); - return false; - } - - PublicKey key = Security.generatePublicKey(base64PublicKey); - return Security.verify(key, signedData, signature); - } - - /** - * Generates a PublicKey instance from a string containing the - * Base64-encoded public key. - * - * @param encodedPublicKey Base64-encoded public key - * @throws IllegalArgumentException if encodedPublicKey is invalid - */ - public static PublicKey generatePublicKey(String encodedPublicKey) { - try { - byte[] decodedKey = Base64.decode(encodedPublicKey); - KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM); - return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey)); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } catch (InvalidKeySpecException e) { - Log.e(TAG, "Invalid key specification."); - throw new IllegalArgumentException(e); - } catch (Base64DecoderException e) { - Log.e(TAG, "Base64 decoding failed."); - throw new IllegalArgumentException(e); - } - } - - /** - * Verifies that the signature from the server matches the computed - * signature on the data. Returns true if the data is correctly signed. - * - * @param publicKey public key associated with the developer account - * @param signedData signed data from server - * @param signature server signature - * @return true if the data and signature match - */ - public static boolean verify(PublicKey publicKey, String signedData, String signature) { - Signature sig; - try { - sig = Signature.getInstance(SIGNATURE_ALGORITHM); - sig.initVerify(publicKey); - sig.update(signedData.getBytes()); - if (!sig.verify(Base64.decode(signature))) { - Log.e(TAG, "Signature verification failed."); - return false; - } - return true; - } catch (NoSuchAlgorithmException e) { - Log.e(TAG, "NoSuchAlgorithmException."); - } catch (InvalidKeyException e) { - Log.e(TAG, "Invalid key specification."); - } catch (SignatureException e) { - Log.e(TAG, "Signature exception."); - } catch (Base64DecoderException e) { - Log.e(TAG, "Base64 decoding failed."); - } - return false; - } -} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/SkuDetails.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/SkuDetails.java deleted file mode 100644 index acdd42f..0000000 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/SkuDetails.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Turbo Editor is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package sharedcode.turboeditor.iab.utils; - -import org.json.JSONException; -import org.json.JSONObject; - -/** - * Represents an in-app product's listing details. - */ -public class SkuDetails { - String mItemType; - String mSku; - String mType; - String mPrice; - String mTitle; - String mDescription; - String mJson; - - public SkuDetails(String jsonSkuDetails) throws JSONException { - this(IabHelper.ITEM_TYPE_INAPP, jsonSkuDetails); - } - - public SkuDetails(String itemType, String jsonSkuDetails) throws JSONException { - mItemType = itemType; - mJson = jsonSkuDetails; - JSONObject o = new JSONObject(mJson); - mSku = o.optString("productId"); - mType = o.optString("type"); - mPrice = o.optString("price"); - mTitle = o.optString("title"); - mDescription = o.optString("description"); - } - - public String getSku() { - return mSku; - } - - public String getType() { - return mType; - } - - public String getPrice() { - return mPrice; - } - - public String getTitle() { - return mTitle; - } - - public String getDescription() { - return mDescription; - } - - @Override - public String toString() { - return "SkuDetails:" + mJson; - } -} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Base64DecoderException.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/PreferenceChangeType.java similarity index 65% rename from libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Base64DecoderException.java rename to libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/PreferenceChangeType.java index 8f4c024..a6432c7 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/iab/utils/Base64DecoderException.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/PreferenceChangeType.java @@ -17,21 +17,8 @@ * along with this program. If not, see . */ -package sharedcode.turboeditor.iab.utils; +package sharedcode.turboeditor.preferences; -/** - * Exception thrown when encountering an invalid Base64 input character. - * - * @author nelson - */ -public class Base64DecoderException extends Exception { - private static final long serialVersionUID = 1L; - - public Base64DecoderException() { - super(); - } - - public Base64DecoderException(String s) { - super(s); - } -} +public enum PreferenceChangeType { + FONT_SIZE, ENCODING, SYNTAX, WRAP_CONTENT, MONOSPACE, LINE_NUMERS, THEME_CHANGE, TEXT_SUGGESTIONS, READ_ONLY, + } \ No newline at end of file diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/PreferenceHelper.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/PreferenceHelper.java index 5b024d1..ca0aaa7 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/PreferenceHelper.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/PreferenceHelper.java @@ -74,7 +74,7 @@ public final class PreferenceHelper { } public static String getEncoding(Context context) { - return getPrefs(context).getString("editor_encoding", "UTF-8"); + return getPrefs(context).getString("editor_encoding", "UTF-16"); } public static int getFontSize(Context context) { diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/SettingsFragment.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/SettingsFragment.java index 5db0fc2..e17666f 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/SettingsFragment.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/preferences/SettingsFragment.java @@ -32,20 +32,7 @@ import sharedcode.turboeditor.R; import sharedcode.turboeditor.activity.MainActivity; import sharedcode.turboeditor.dialogfragment.EncodingDialog; import sharedcode.turboeditor.dialogfragment.NumberPickerDialog; -import sharedcode.turboeditor.util.ProCheckUtils; import sharedcode.turboeditor.util.ViewUtils; -import sharedcode.turboeditor.views.DialogHelper; - -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.ENCODING; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.FONT_SIZE; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.LINE_NUMERS; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.MONOSPACE; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.READ_ONLY; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.SYNTAX; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.TEXT_SUGGESTIONS; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.THEME_CHANGE; -import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.WRAP_CONTENT; public class SettingsFragment extends Fragment implements NumberPickerDialog.INumberPickerDialog, EncodingDialog.DialogListener { @@ -118,16 +105,12 @@ public class SettingsFragment extends Fragment implements NumberPickerDialog.INu fontSizeView = (TextView) rootView.findViewById(R.id.drawer_button_font_size); encodingView = (TextView) rootView.findViewById(R.id.drawer_button_encoding); extraOptionsView = (TextView) rootView.findViewById(R.id.drawer_button_extra_options); - donateView = (TextView) rootView.findViewById(R.id.drawer_button_go_pro); - - if(ProCheckUtils.isPro(getActivity(), false)) - ViewUtils.setVisible(donateView, false); swLineNumbers.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { PreferenceHelper.setLineNumbers(getActivity(), isChecked); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(LINE_NUMERS)); + ((MainActivity) getActivity()).aPreferenceValueWasChanged(PreferenceChangeType.LINE_NUMERS); } }); @@ -136,7 +119,7 @@ public class SettingsFragment extends Fragment implements NumberPickerDialog.INu public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { sColorSyntax = isChecked; PreferenceHelper.setSyntaxHighlight(getActivity(), isChecked); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(SYNTAX)); + ((MainActivity) getActivity()).aPreferenceValueWasChanged(PreferenceChangeType.SYNTAX); } }); @@ -145,7 +128,7 @@ public class SettingsFragment extends Fragment implements NumberPickerDialog.INu @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { PreferenceHelper.setWrapContent(getActivity(), isChecked); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(WRAP_CONTENT)); + ((MainActivity) getActivity()).aPreferenceValueWasChanged(PreferenceChangeType.WRAP_CONTENT); } }); @@ -154,7 +137,7 @@ public class SettingsFragment extends Fragment implements NumberPickerDialog.INu public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { sUseMonospace = isChecked; PreferenceHelper.setUseMonospace(getActivity(), isChecked); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(MONOSPACE)); + ((MainActivity) getActivity()).aPreferenceValueWasChanged(PreferenceChangeType.MONOSPACE); } }); @@ -163,7 +146,7 @@ public class SettingsFragment extends Fragment implements NumberPickerDialog.INu @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { PreferenceHelper.setReadOnly(getActivity(), isChecked); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(READ_ONLY)); + ((MainActivity) getActivity()).aPreferenceValueWasChanged(PreferenceChangeType.READ_ONLY); } }); @@ -200,18 +183,11 @@ public class SettingsFragment extends Fragment implements NumberPickerDialog.INu } }); - donateView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - DialogHelper.showDonateDialog(getActivity()); - } - }); - swLightTheme.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { PreferenceHelper.setLightTheme(getActivity(), isChecked); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(THEME_CHANGE)); + ((MainActivity) getActivity()).aPreferenceValueWasChanged(PreferenceChangeType.THEME_CHANGE); } }); @@ -219,7 +195,7 @@ public class SettingsFragment extends Fragment implements NumberPickerDialog.INu @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { PreferenceHelper.setSuggestionsActive(getActivity(), isChecked); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(TEXT_SUGGESTIONS)); + ((MainActivity) getActivity()).aPreferenceValueWasChanged(PreferenceChangeType.TEXT_SUGGESTIONS); } }); @@ -257,13 +233,13 @@ public class SettingsFragment extends Fragment implements NumberPickerDialog.INu @Override public void onNumberPickerDialogDismissed(NumberPickerDialog.Actions action, int value) { PreferenceHelper.setFontSize(getActivity(), value); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(FONT_SIZE)); + ((MainActivity) getActivity()).aPreferenceValueWasChanged(PreferenceChangeType.FONT_SIZE); } @Override public void onEncodingSelected(String result) { PreferenceHelper.setEncoding(getActivity(), result); - ((MainActivity) getActivity()).onEvent(new APreferenceValueWasChanged(ENCODING)); + ((MainActivity) getActivity()).aPreferenceValueWasChanged(PreferenceChangeType.ENCODING); } } diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/task/SaveFileTask.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/task/SaveFileTask.java index 69b8bb2..0819b6a 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/task/SaveFileTask.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/task/SaveFileTask.java @@ -32,7 +32,6 @@ import java.util.concurrent.TimeoutException; import sharedcode.turboeditor.R; import sharedcode.turboeditor.activity.MainActivity; import sharedcode.turboeditor.root.RootUtils; -import sharedcode.turboeditor.util.EventBusEvents; public class SaveFileTask extends AsyncTask { @@ -101,6 +100,6 @@ public class SaveFileTask extends AsyncTask { super.onPostExecute(aVoid); Toast.makeText(activity, message, Toast.LENGTH_LONG).show(); if (message.equals(positiveMessage)) - activity.onEvent(new EventBusEvents.SavedAFile(filePath)); + activity.savedAFile(filePath); } } \ No newline at end of file diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/LineUtils.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/LineUtils.java index f6505ce..40e6502 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/LineUtils.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/LineUtils.java @@ -27,7 +27,7 @@ public class LineUtils { private boolean[] toCountLinesArray; private int[] realLines; - public boolean[] getToCountLinesArray() { + public boolean[] getGoodLines() { return toCountLinesArray; } @@ -81,6 +81,8 @@ public class LineUtils { } } + toCountLinesArray[lineCount-1] = true; + int realLine = startingLine; // the first line is not 0, is 1. We start counting from 1 for (i = 0; i < toCountLinesArray.length; i++) { diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/Patterns.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/Patterns.java index 483fb96..cca92e6 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/Patterns.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/Patterns.java @@ -35,10 +35,8 @@ public class Patterns { // Strings public static final Pattern GENERAL_STRINGS = Pattern.compile("\"(.*?)\"|'(.*?)'"); - public static final Pattern HTML_OPEN_TAGS = Pattern.compile( - "<([A-Za-z][A-Za-z0-9]*)\\b[^>]*>"); - public static final Pattern HTML_CLOSE_TAGS = Pattern.compile( - "]*>"); + public static final Pattern HTML_TAGS = Pattern.compile( + "<([A-Za-z][A-Za-z0-9]*)\\b[^>]*>|]*>"); public static final Pattern HTML_ATTRS = Pattern.compile( "(\\S+)=[\"']?((?:.(?![\"']?\\s+(?:\\S+)=|[>\"']))+.)[\"']?"); @@ -54,7 +52,7 @@ public class Patterns { //public static final Pattern CSS_NUMBERS = Pattern.compile( // "/^auto$|^[+-]?[0-9]+\\.?([0-9]+)?(px|em|ex|%|in|cm|mm|pt|pc)?$/ig"); public static final Pattern SYMBOLS = Pattern.compile( - "(!|,|\\(|\\)|\\+|\\-|\\*|<|>|=|\\.|\\?|;|\\{|\\}|\\[|\\])"); + "(!|,|\\(|\\)|\\+|\\-|\\*|<|>|=|\\.|\\?|;|\\{|\\}|\\[|\\]|\\|)"); public static final Pattern NUMBERS_OR_SYMBOLS = Pattern.compile(NUMBERS.pattern()+"|"+SYMBOLS.pattern()); public static final Pattern GENERAL_KEYWORDS = Pattern.compile( "\\b(alignas|alignof|and|and_eq|asm|auto|bitand|bitorbool|break|case|catch|char|" diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/SearchResult.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/SearchResult.java index 1105101..2475db4 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/SearchResult.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/texteditor/SearchResult.java @@ -28,11 +28,14 @@ public class SearchResult { public boolean isReplace; public String textToReplace; public int index; + public String whatToSearch; - public SearchResult(LinkedList foundIndex, int textLength, boolean isReplace, String textToReplace) { + + public SearchResult(LinkedList foundIndex, int textLength, boolean isReplace, String whatToSearch, String textToReplace) { this.foundIndex = foundIndex; this.textLength = textLength; this.isReplace = isReplace; + this.whatToSearch = whatToSearch; this.textToReplace = textToReplace; } diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/EventBusEvents.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/EventBusEvents.java deleted file mode 100644 index 9505a42..0000000 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/EventBusEvents.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2014 Vlad Mihalachi - * - * This file is part of Turbo Editor. - * - * Turbo Editor is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Turbo Editor is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package sharedcode.turboeditor.util; - -import java.io.File; -import java.util.List; - -public class EventBusEvents { - public static class CannotOpenAFile { - - } - - public static class NewFileToOpen { - - private final File file; - private final String fileText; - - public NewFileToOpen(File file) { - this.file = file; - this.fileText = ""; - } - - public NewFileToOpen(String fileText) { - this.file = new File(""); - this.fileText = fileText; - } - - public File getFile() { - return file; - } - - public String getFileText() { - return fileText; - } - } - - public static class AFileIsSelected { - - private final String path; - - public AFileIsSelected(String path) { - this.path = path; - } - - public String getPath() { - return path; - } - } - - public static class APreferenceValueWasChanged { - private Type type; - private List types; - - public APreferenceValueWasChanged(Type type) { - this.type = type; - } - - public APreferenceValueWasChanged(List types) { - this.types = types; - } - - public boolean hasType(Type value) { - - if (type != null) { - return value == type; - } else { - return types.contains(value); - } - - } - - public enum Type { - FONT_SIZE, ENCODING, SYNTAX, WRAP_CONTENT, MONOSPACE, LINE_NUMERS, THEME_CHANGE, TEXT_SUGGESTIONS, READ_ONLY, - } - } - - public static class SaveAFile { - } - - public static class SavedAFile { - private final String path; - - public SavedAFile(String path) { - this.path = path; - } - - public String getPath() { - return path; - } - } - - public static class ClosedAFile { - } - - public static class InvalideTheMenu { - } - -} diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/ProCheckUtils.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/ProCheckUtils.java index c9af73c..a7a1268 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/ProCheckUtils.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/util/ProCheckUtils.java @@ -21,21 +21,20 @@ package sharedcode.turboeditor.util; import android.content.Context; -import sharedcode.turboeditor.preferences.PreferenceHelper; - public class ProCheckUtils { public static boolean isPro(Context context, boolean includeDonations) { - String packageName = context.getPackageName(); - + // happy new year + return true; + /* if (Build.FOR_AMAZON) return true; - else if (packageName.equals("com.maskyn.fileeditorpro")) + else if (context.getPackageName().equals("com.maskyn.fileeditorpro")) return true; else if (includeDonations && PreferenceHelper.hasDonated(context)) return true; else - return false; + return false;*/ } public static boolean isPro(Context context) { diff --git a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/views/DialogHelper.java b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/views/DialogHelper.java index 19e2ee0..a5b9fc2 100644 --- a/libraries/sharedCode/src/main/java/sharedcode/turboeditor/views/DialogHelper.java +++ b/libraries/sharedCode/src/main/java/sharedcode/turboeditor/views/DialogHelper.java @@ -39,7 +39,6 @@ import org.apache.commons.lang3.builder.HashCodeBuilder; import sharedcode.turboeditor.R; import sharedcode.turboeditor.dialogfragment.AboutDialog; -import sharedcode.turboeditor.iab.DonationFragment; /** * Helper class for showing fragment dialogs. @@ -48,13 +47,8 @@ public class DialogHelper { public static final String TAG_FRAGMENT_ABOUT = "dialog_about"; public static final String TAG_FRAGMENT_HELP = "dialog_help"; - public static final String TAG_FRAGMENT_DONATION = "dialog_donate"; public static final String TAG_FRAGMENT_FEEDBACK = "dialog_feedback"; - public static void showDonateDialog(Activity activity) { - showDialog(activity, DonationFragment.class, TAG_FRAGMENT_DONATION); - } - public static void showAboutDialog(Activity activity) { showDialog(activity, AboutDialog.class, TAG_FRAGMENT_ABOUT); } diff --git a/libraries/sharedCode/src/main/res/layout/activity_home.xml b/libraries/sharedCode/src/main/res/layout/activity_home.xml index 1cb26e4..d2a6573 100644 --- a/libraries/sharedCode/src/main/res/layout/activity_home.xml +++ b/libraries/sharedCode/src/main/res/layout/activity_home.xml @@ -18,16 +18,11 @@ ~ You should have received a copy of the GNU General Public License ~ along with this program. If not, see . --> - - + @@ -43,6 +38,14 @@ android:textColor="@android:color/secondary_text_dark" android:id="@id/no_file_opened_messagge"/> + + + + - + @@ -153,7 +156,7 @@ - - diff --git a/libraries/sharedCode/src/main/res/layout/dialog_fragment_new_file_details.xml b/libraries/sharedCode/src/main/res/layout/dialog_fragment_new_file_details.xml index 1964a11..b2749f8 100644 --- a/libraries/sharedCode/src/main/res/layout/dialog_fragment_new_file_details.xml +++ b/libraries/sharedCode/src/main/res/layout/dialog_fragment_new_file_details.xml @@ -58,4 +58,14 @@ android:hint="@string/folder" android:padding="5dp" android:textSize="12sp"/> + + diff --git a/libraries/sharedCode/src/main/res/layout/donation_dialog.xml b/libraries/sharedCode/src/main/res/layout/donation_dialog.xml deleted file mode 100644 index 2132d23..0000000 --- a/libraries/sharedCode/src/main/res/layout/donation_dialog.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/libraries/sharedCode/src/main/res/layout/donation_iab_item.xml b/libraries/sharedCode/src/main/res/layout/donation_iab_item.xml deleted file mode 100644 index d931d87..0000000 --- a/libraries/sharedCode/src/main/res/layout/donation_iab_item.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/libraries/sharedCode/src/main/res/layout/fragment_settings.xml b/libraries/sharedCode/src/main/res/layout/fragment_settings.xml index 7e93fb1..a152708 100644 --- a/libraries/sharedCode/src/main/res/layout/fragment_settings.xml +++ b/libraries/sharedCode/src/main/res/layout/fragment_settings.xml @@ -32,21 +32,6 @@ android:orientation="vertical" > - - +

+ + + + + - diff --git a/libraries/sharedCode/src/main/res/menu/fragment_editor_search.xml b/libraries/sharedCode/src/main/res/menu/fragment_editor_search.xml index 266aebd..70adc42 100644 --- a/libraries/sharedCode/src/main/res/menu/fragment_editor_search.xml +++ b/libraries/sharedCode/src/main/res/menu/fragment_editor_search.xml @@ -49,6 +49,11 @@ app:showAsAction="always" android:title="@string/replace"> + + Spenden - Donate to developer + An den Entwickler spenden open source app. - You can show your appreciation and support development by donating: + Turbo Editor ist eine freie und quelloffene Anwendung. + Du kannst deine Anerkennung zeigen, in dem du die Entwicklung mit Spenden unterstützt: ]]> - You\'ve donated for this item already. - An ice cream - Cup of coffee - Electricity bills - The right pillow - Solid-state drive - Sound system - Failed to setup in-app-billing service! - Notice that Google is not responsible for that payments method. + Du hast bereits gespendet. + Eine Kugel Eis + Tasse Kaffee + Stromrechnung + Das richtige Kissen + SSD Festplatte + Sound-System + Fehler beim Einrichten des In-App-Bezahlservices! + Beachten Sie, dass Google für diese Zahlungsmethode nicht verantwortlich ist. diff --git a/libraries/sharedCode/src/main/res/values-es-rES/strings.xml b/libraries/sharedCode/src/main/res/values-es-rES/strings.xml index 6f0241b..4e88eab 100644 --- a/libraries/sharedCode/src/main/res/values-es-rES/strings.xml +++ b/libraries/sharedCode/src/main/res/values-es-rES/strings.xml @@ -28,7 +28,7 @@ Ajuste de línea Ver en la web Archivo - archivo + Carpeta Tema claro Ir a línea Ir a página… diff --git a/libraries/sharedCode/src/main/res/values-es-rES/strings_donation.xml b/libraries/sharedCode/src/main/res/values-es-rES/strings_donation.xml index 17ef599..078efe3 100644 --- a/libraries/sharedCode/src/main/res/values-es-rES/strings_donation.xml +++ b/libraries/sharedCode/src/main/res/values-es-rES/strings_donation.xml @@ -20,7 +20,7 @@ --> Donar - Donate to developer + Donar al desarrollador open source app. You can show your appreciation and support development by donating: diff --git a/libraries/sharedCode/src/main/res/values-fi-rFI/strings.xml b/libraries/sharedCode/src/main/res/values-fi-rFI/strings.xml index fbb5d27..d04b4e7 100644 --- a/libraries/sharedCode/src/main/res/values-fi-rFI/strings.xml +++ b/libraries/sharedCode/src/main/res/values-fi-rFI/strings.xml @@ -30,7 +30,7 @@ Tiedosto Kansio Vaalea teema - Siirry riville + Siirry riville… Siirry sivulle… Löydä Korvaa @@ -51,7 +51,7 @@ Auta kääntämisessä Muutosloki Sama kirjainkoko - Saat lisää vaihtoehtoja napsauttamalla + Saat lisää vaihtoehtoja pitkällä painalluksella Automaattinen tallennus Vain luku Lähetä virheraportit diff --git a/libraries/sharedCode/src/main/res/values-fi-rFI/strings_dialogs.xml b/libraries/sharedCode/src/main/res/values-fi-rFI/strings_dialogs.xml index e8ce99d..7e74ba6 100644 --- a/libraries/sharedCode/src/main/res/values-fi-rFI/strings_dialogs.xml +++ b/libraries/sharedCode/src/main/res/values-fi-rFI/strings_dialogs.xml @@ -22,12 +22,12 @@ Sulje Tietoja avoimen lähdekoodin sovellus. + Turbo Editor on ilmainen ja avoimen lähdekoodin sovellus. Tekijänoikeudet 2013-2014 Vlad Mihalachi. Kaikki oikeudet pidätetään.

Suuret kiitokset kaikille, jotka auttoivat käännöksien parissa tai - lahjoittivat minulle.
+ lahjoittivat minulle.

Jos haluat lähettää palautetta, kerro se siitä XDA-ketjussa ]]>
diff --git a/libraries/sharedCode/src/main/res/values-fi-rFI/strings_donation.xml b/libraries/sharedCode/src/main/res/values-fi-rFI/strings_donation.xml index ea9cee6..140a157 100644 --- a/libraries/sharedCode/src/main/res/values-fi-rFI/strings_donation.xml +++ b/libraries/sharedCode/src/main/res/values-fi-rFI/strings_donation.xml @@ -28,7 +28,7 @@ Olet lahjoittanut tälle kohteelle jo. Jäätelöä Kuppi kahvia - Sähkölasku + Sähkölaskut Oikea tyyny SSD-levy Äänijärjestelmä diff --git a/libraries/sharedCode/src/main/res/values-hi-rIN/strings.xml b/libraries/sharedCode/src/main/res/values-hi-rIN/strings.xml index ba3c203..d6f2178 100644 --- a/libraries/sharedCode/src/main/res/values-hi-rIN/strings.xml +++ b/libraries/sharedCode/src/main/res/values-hi-rIN/strings.xml @@ -20,13 +20,13 @@ --> - Use monospace - Recent files + Monospace को उपयोग करें + हाल ही की दस्तावेज Font size Connection Name - Line Numbers - Wrap content - View it on the web + पंक्ति क्रमांक + सामग्री लपेटें + यह वेब पर देखें File Folder Light Theme diff --git a/libraries/sharedCode/src/main/res/values-hu-rHU/strings.xml b/libraries/sharedCode/src/main/res/values-hu-rHU/strings.xml index 1d5ce96..eb89e39 100644 --- a/libraries/sharedCode/src/main/res/values-hu-rHU/strings.xml +++ b/libraries/sharedCode/src/main/res/values-hu-rHU/strings.xml @@ -31,7 +31,7 @@ Mappa Világos téma Sorhoz ugrás - Go to Page… + Ugrás oldalra… Keresés Csere Megosztás @@ -54,11 +54,11 @@ Hosszú-kattintás a további beállításokhoz Automatikus mentés Csak olvasható - Send error reports - Extra options - Split the text if too long - Ignore back button - Donate + Hibajelentés küldése + Extra beállítások + A szöveg részekre bontása ha túl hosszú + Vissza-gomb figyelmen kívül hagyása + Támogatás Kódolás Megosztás Információ @@ -71,6 +71,6 @@ Megnyit A(z) %1$s fájl sikeresen mentve! Fájl megnyitása - No - New file + Nem + Új fájl diff --git a/libraries/sharedCode/src/main/res/values-hu-rHU/strings_dialogs.xml b/libraries/sharedCode/src/main/res/values-hu-rHU/strings_dialogs.xml index ad64876..f5ee4a1 100644 --- a/libraries/sharedCode/src/main/res/values-hu-rHU/strings_dialogs.xml +++ b/libraries/sharedCode/src/main/res/values-hu-rHU/strings_dialogs.xml @@ -19,16 +19,16 @@ ~ along with this program. If not, see . --> - Close - About + Bezárás + Névjegy open source app. + A Turbo Editor szabad és nyílt forráskódú alkalmazás. Copyright 2013-2014 Vlad Mihalachi. All Rights Reserved.

- Many thanks to all who - helped with translations or - donated to me.
+ Köszönet mindazoknak akik + segítettek a fordításban vagy + támogatást adtak.

- If you want to send feedback here is the XDA thread + Visszajelzéseket az XDA fórumon lehet küldeni ]]>
diff --git a/libraries/sharedCode/src/main/res/values-hu-rHU/strings_donation.xml b/libraries/sharedCode/src/main/res/values-hu-rHU/strings_donation.xml index 9b2bcc8..e51221a 100644 --- a/libraries/sharedCode/src/main/res/values-hu-rHU/strings_donation.xml +++ b/libraries/sharedCode/src/main/res/values-hu-rHU/strings_donation.xml @@ -19,19 +19,19 @@ ~ along with this program. If not, see . --> - Donate - Donate to developer + Támogatás + Támogatás a fejlesztőnek open source app. - You can show your appreciation and support development by donating: + A Turbo Editor egy szabad és nyílt forrású alkalmazás. + Mutassa meg mennyire értékeli és támogathassa a fejlesztést: ]]> - You\'ve donated for this item already. - An ice cream - Cup of coffee - Electricity bills - The right pillow - Solid-state drive - Sound system - Failed to setup in-app-billing service! - Notice that Google is not responsible for that payments method. + Ön már támogatta ezt. + Egy jégkrém + Egy csésze kávé + Villany számla + A jobb oldali párna + Szilárdtest-meghajtó + Hang-rendszer + Nem sikerült beállítani az alkalmazáson belüli fizetést! + Ne felejtse el, hogy a Google nem felel a fizetési módszerekért. diff --git a/libraries/sharedCode/src/main/res/values-in-rID/strings.xml b/libraries/sharedCode/src/main/res/values-in-rID/strings.xml index d4f7cbb..ef66929 100644 --- a/libraries/sharedCode/src/main/res/values-in-rID/strings.xml +++ b/libraries/sharedCode/src/main/res/values-in-rID/strings.xml @@ -25,52 +25,52 @@ Ukuran font Nama Sambungan Nomor Baris - Wrap Konten + Rapatkan Konten Lihat di web File Folder Tema Terang Pergi ke Baris - Go to Page… - Cari - Replace + Pergi ke halaman... + Temukan + Ganti Bagikan - Keyboard suggestions and Swipe + Saran keyboard dan usapan Pengkodean-Otomatis - Set as the working folder - This is the working folder - Do you want to save the changes to the file %s? - Regular Expression - Text to find - Text to replace - Next - Previous - Please wait… - %s occurrences was found + Jadikan sebagai folder kerja + Ini adalah folder kerja + Apakah Anda ingin menyimpan perubahan pada file ini %s? + Ekspresi Reguler + Ketik untuk mencari + Ketik untuk mengganti + Lanjut + Sebelum + Harap tunggu... + %s kejadian ditemukan v%s - Translate - Changelog - Match case - Long click for more options - Auto save - Read only - Send error reports - Extra options - Split the text if too long - Ignore back button - Donate + Terjemahkan + Daftar perubahan + Penyesuaian + Klik tahan untuk opsi lanjut + Simpan otomatis + Hanya baca + Kirim laporan kesalahan + Opsi ekstra + Membagi teks jika terlalu panjang + Abaikan tombol kembali + Donasi Pengkodean Bagikan Info - Editor Turbo + Turbo Editor Preferensi Simpan - Highlight syntax - Batal + Sorot sintaks + Batalkan Ulangi Buka File %1$s berhasil disimpan! Buka file - No - New file + Tidak + File baru
diff --git a/libraries/sharedCode/src/main/res/values-in-rID/strings_dialogs.xml b/libraries/sharedCode/src/main/res/values-in-rID/strings_dialogs.xml index ad64876..cee0958 100644 --- a/libraries/sharedCode/src/main/res/values-in-rID/strings_dialogs.xml +++ b/libraries/sharedCode/src/main/res/values-in-rID/strings_dialogs.xml @@ -19,16 +19,15 @@ ~ along with this program. If not, see . --> - Close - About + Tutup + Tentang open source app. - Copyright 2013-2014 Vlad Mihalachi. All Rights Reserved.
-
- Many thanks to all who - helped with translations or - donated to me.
-
- If you want to send feedback here is the XDA thread - ]]>
+Turbo Editor adalah sebuah aplikasi gratis dan open source app. +Copyright 2013-2014 Vlad Mihalachi. All Rights Reserved.
+
+Banyak terima kasih saya ucapkan kepada +yang telah membantu menerjemahkan aplikasi ini or +donasi kepada saya.
+
+Jika Anda ingin mengirim saran atau kritik Artikel di XDA ]]>
diff --git a/libraries/sharedCode/src/main/res/values-in-rID/strings_donation.xml b/libraries/sharedCode/src/main/res/values-in-rID/strings_donation.xml index 9b2bcc8..f6905c7 100644 --- a/libraries/sharedCode/src/main/res/values-in-rID/strings_donation.xml +++ b/libraries/sharedCode/src/main/res/values-in-rID/strings_donation.xml @@ -19,19 +19,18 @@ ~ along with this program. If not, see . --> - Donate - Donate to developer + Donasi + Donasi untuk pengembang open source app. - You can show your appreciation and support development by donating: - ]]> - You\'ve donated for this item already. - An ice cream - Cup of coffee - Electricity bills - The right pillow - Solid-state drive - Sound system - Failed to setup in-app-billing service! - Notice that Google is not responsible for that payments method. +Turbo Editor adalah sebuah aplikasi gratis dani open source app. +Anda dapat melihat apresiasi Anda dan dukungan pada pengembang dengan memberikan donasi: ]]> + Anda telah mendonasikan untuk item ini. + Sebuah es krim + Secangkir kopi + Tagihan listrik + Bantal yang tepat + Solid-state drive (SSD) + Sistem suara + Gagal dalam menyeting layanan pembelian dalam aplikasi! + Perhatikan bahwa Google tidak bertanggung jawab untuk metode pembayaran. diff --git a/libraries/sharedCode/src/main/res/values-pl-rPL/strings.xml b/libraries/sharedCode/src/main/res/values-pl-rPL/strings.xml index f9be2d0..2c0a860 100644 --- a/libraries/sharedCode/src/main/res/values-pl-rPL/strings.xml +++ b/libraries/sharedCode/src/main/res/values-pl-rPL/strings.xml @@ -31,7 +31,7 @@ Folder Jasny motyw Idź do linii - Go to Page… + Idź do strony… Znajdź Zastąp Udostępnij @@ -47,18 +47,18 @@ Poprzedni Proszę czekać… Znaleziono %s wystąpień - v%s + wersja %s Tłumacz Lista zmian Uwzględnij wielkość liter Przytrzymaj dłużej aby zobaczyć więcej opcji Automatyczny zapis Tylko do odczytu - Send error reports - Extra options - Split the text if too long - Ignore back button - Donate + Wyślij raport o błędach + Dodatkowe opcje + Podziel tekst, jeśli jest zbyt długi + Ignoruj przycisk \"Wstecz\" + Wesprzyj mnie Kodowanie Udostępnij Informacje @@ -71,6 +71,6 @@ Otwórz Plik %1$s został pomyślnie zapisany! Otwórz plik - No - New file + Nie + Nowy plik diff --git a/libraries/sharedCode/src/main/res/values-pl-rPL/strings_dialogs.xml b/libraries/sharedCode/src/main/res/values-pl-rPL/strings_dialogs.xml index ad64876..c081ac9 100644 --- a/libraries/sharedCode/src/main/res/values-pl-rPL/strings_dialogs.xml +++ b/libraries/sharedCode/src/main/res/values-pl-rPL/strings_dialogs.xml @@ -19,8 +19,8 @@ ~ along with this program. If not, see . --> - Close - About + Zamknij + O aplikacji i autorach open source app. Copyright 2013-2014 Vlad Mihalachi. All Rights Reserved.
diff --git a/libraries/sharedCode/src/main/res/values-pl-rPL/strings_donation.xml b/libraries/sharedCode/src/main/res/values-pl-rPL/strings_donation.xml index 9b2bcc8..96c9dff 100644 --- a/libraries/sharedCode/src/main/res/values-pl-rPL/strings_donation.xml +++ b/libraries/sharedCode/src/main/res/values-pl-rPL/strings_donation.xml @@ -19,8 +19,8 @@ ~ along with this program. If not, see . --> - Donate - Donate to developer + Wesprzyj mnie + Wspomóż twórcę open source app. You can show your appreciation and support development by donating: diff --git a/libraries/sharedCode/src/main/res/values-pt-rBR/strings.xml b/libraries/sharedCode/src/main/res/values-pt-rBR/strings.xml index 0e19838..f46e1c6 100644 --- a/libraries/sharedCode/src/main/res/values-pt-rBR/strings.xml +++ b/libraries/sharedCode/src/main/res/values-pt-rBR/strings.xml @@ -71,6 +71,6 @@ Abrir O arquivo %1$s foi salvo com sucesso! Abrir um arquivo - No - New file + Não + Novo arquivo diff --git a/libraries/sharedCode/src/main/res/values-ru-rRU/strings.xml b/libraries/sharedCode/src/main/res/values-ru-rRU/strings.xml index 9788828..9158cfb 100644 --- a/libraries/sharedCode/src/main/res/values-ru-rRU/strings.xml +++ b/libraries/sharedCode/src/main/res/values-ru-rRU/strings.xml @@ -30,13 +30,13 @@ Файл Каталог Светлая тема - Перейти к строке + Перейти к строке… Перейти на страницу… Поиск Заменить Поделиться - Car - Copy + Показывать варианты исправлений + Автоопределение кодировки Установить в качестве рабочего каталога Это рабочий каталог Сохранить изменения в файле %s? @@ -54,7 +54,7 @@ Долгое нажатие для дополнительных опций Автосохранение Только для чтения - Отправить отчёт об ошибке + Отправлять отчёты об ошибках Дополнительные опции Разбивать длинный текст Игнорировать кнопку Назад diff --git a/libraries/sharedCode/src/main/res/values-ru-rRU/strings_donation.xml b/libraries/sharedCode/src/main/res/values-ru-rRU/strings_donation.xml index a99fd86..9549f7f 100644 --- a/libraries/sharedCode/src/main/res/values-ru-rRU/strings_donation.xml +++ b/libraries/sharedCode/src/main/res/values-ru-rRU/strings_donation.xml @@ -20,18 +20,18 @@ --> Поддержать - Donate to developer + Пожертвовать разработчику open source app. - You can show your appreciation and support development by donating: + Turbo Editor является бесплатной и open source программой. + Вы можете выразить свою признательность и поддержку, пожертвовав: ]]> - You\'ve donated for this item already. - An ice cream - Cup of coffee - Electricity bills - The right pillow - Solid-state drive - Sound system - Failed to setup in-app-billing service! - Notice that Google is not responsible for that payments method. + Вы уже пожертвовали. + Мороженое + Чашка кофе + Счета за электричество + Отличная подушка + Твердотельный накопитель + Звуковая система + Не удалось запустить внутреннюю службу биллинга! + Имейте в виду, что Google не несет ответственности за данный способ оплаты. diff --git a/libraries/sharedCode/src/main/res/values-sk-rSK/strings.xml b/libraries/sharedCode/src/main/res/values-sk-rSK/strings.xml index 7bb7364..938d451 100644 --- a/libraries/sharedCode/src/main/res/values-sk-rSK/strings.xml +++ b/libraries/sharedCode/src/main/res/values-sk-rSK/strings.xml @@ -1,153 +1,76 @@ - - - - - - - Nový účet - Aktívne - Vymazať - Mažem súbory… - Načítavanie… - Aktuálna miestna zložka - Súkromný kľúč - Svetlá - Kódovanie - Zdieľať - Nový lokálny súbor - Nový vzdialený priečinok - New remote file - New local file - Odpojiť sa - Predvol. miestna zložka - Kde oi chcete stiahnuť? - Stiahnuť - Sťahovanie dokončené - Duplikát - Hotovo - Domov - Hosť - Info - Lokálny - Prihlasujem sa… - Upraviť - Presunúť - Schovať - Turbo Klient - Turbo Editor - Užív. meno - Pasívny - Heslo - Heslo - Ponechajte prázdne, pre výzvu pri každej relácii - Port - Predvoľby - vzdialený - Pre zmenu témy, reštartujte aplikáciu - Premenovať - Root - Uložiť - Tmavá - Vybrať - Vyberte účet - Ste si istý? - Niečo zlyhalo - Nepresúvajte rovnaký súbor - Téma - Typ pripojenia - Typ protokolu - Ďalšia zložka - Napíš heslo - Nahrať - Nahrávanie dokončené - Čo chceš robiť? - Syntax highlight - Vrátiť späť - Prerobiť - Synchronizovať - Vzdial. zložka na synchronizáciu - Miestna zložka na synchronizáciu - Ohodnotiť - Nemožno kontaktovať Google Play - Podpor rozvoj ďalších skvelých funkcií. - Vylepšiť na Premium - Vylepši na Premium a podpor tým vývoj Turbo klienta! - Stiahnuť odomknutú verziu - Čo pre teba Turbo klient znamená? Stanov si vlastnú cenu! - Vylepši na Premium, pre odomknutie týchto funkcií: - Power to open and modify any type of file. - Backup service to backup and restore your data safely. - Unlock the Premium features - I really like this app! - I love this app! - Backup the accounts - Restore the accounts - Backup and share the accounts - Importing the accounts… - Exporting the accounts... - No backups found - Cannot open the file - Temporary folder does not exist - An error occurred - Ui - Remove - Modification date - Name - Size - Sort - Open - The file %1$s was modified, do you want to upload it? - The file %1$s was saved with success! - Create a new account - Create a new account to start. - Type - Send feedback - Copy URL - Cut - paste - Advanced - Auto - Bytes - Unit of measurement for file size - Open Source licenses - Show open source licenses - Open a file - Open this time only - Change the list type - Use monospace - Recent files - Font size - Connection Name - Line Numbers - Wrap content - View it on the web - The file size is too big - Search - Add - File - Folder - Light Theme - Goto Line - Find - Find and Replace - Root Permission - Zdieľať - Text Suggestions - + + + + + + Použiť neproporcionálne + Nedávne súbory + Veľkosť písma + Názov pripojenia + Čísla riadkov + Zalomiť obsah + Zobraziť na webe + Súbor + Adresár + Svetlá téma + Prejsť na riadok… + Prejsť na stránku… + Nájsť + Nahradiť + Zdieľať + Návrhy opráv a písanie gestami + Automatické kódovanie + Nastaviť ako pracovný adresár + Toto je pracovný adresár + Chcete uložiť zmeny v súbore %s? + Presný výraz + Text, ktorý chcete nájsť + Text, ktorý chcete nahradiť + Ďalšie + Predchádzajúce + Prosím, počkajte… + %s výskytov bolo nájdených + v%s + Preložiť + Zoznam zmien + Rozlišovať malé a veľké písmená + Podržte dlhšie pre viac možností + Automatické ukladanie + Iba na čítanie + Odoslať správy o chybách + Ďalšie voľby + Rozdeliť text, ak je príliš dlhý + Ignorovať tlačidlo späť + Prispieť + Kódovanie + Zdieľať + Informácie + Turbo Editor + Predvoľby + Uložiť + Zvýrazniť syntax + Späť + Znova + Otvoriť + Súbor %1$s bol úspešne uložený! + Otvoriť súbor + Nie + Nový súbor + diff --git a/libraries/sharedCode/src/main/res/values/integers.xml b/libraries/sharedCode/src/main/res/values-sk-rSK/strings_dialogs.xml similarity index 50% rename from libraries/sharedCode/src/main/res/values/integers.xml rename to libraries/sharedCode/src/main/res/values-sk-rSK/strings_dialogs.xml index 5768659..f03d946 100644 --- a/libraries/sharedCode/src/main/res/values/integers.xml +++ b/libraries/sharedCode/src/main/res/values-sk-rSK/strings_dialogs.xml @@ -1,23 +1,34 @@ - - - - - 4194304 - + + + + + Zatvoriť + O aplikácii + zdrojový kód je voľné dostupný. + Copyright 2013-2014 Vlad Mihalachi. Všetky práva vyhradené.
+
+ Veľká vďaka všetkým + prekladateľom aj tým, + ktorí mi poslali dar.
+
+ Svoj názor na aplikáciu môžete vyjadriť v téme na XDA + ]]>
+
diff --git a/libraries/sharedCode/src/main/res/values-sk-rSK/strings_donation.xml b/libraries/sharedCode/src/main/res/values-sk-rSK/strings_donation.xml new file mode 100644 index 0000000..e98076a --- /dev/null +++ b/libraries/sharedCode/src/main/res/values-sk-rSK/strings_donation.xml @@ -0,0 +1,37 @@ + + + + + Prispieť + Podporiť vývojára + zdrojový kód je voľné dostupný. + Môžete ukázať svoje uznanie a podporiť rozvoj tým, že pošlete dar: + ]]> + Už ste pre túto položku poslali dar. + Zmrzlina + Šálka kávy + Účet za elektrinu + Správny vankúš + SSD disk + Domáce kino + Zlyhalo nastavenie služby nákupu v aplikácii! + Prosím, berte na vedomie, že Google nie je zodpovedný za túto metódu platby. + diff --git a/libraries/sharedCode/src/main/res/values-sv-rSE/strings.xml b/libraries/sharedCode/src/main/res/values-sv-rSE/strings.xml index bfcb5d9..e80f6d5 100644 --- a/libraries/sharedCode/src/main/res/values-sv-rSE/strings.xml +++ b/libraries/sharedCode/src/main/res/values-sv-rSE/strings.xml @@ -21,56 +21,56 @@ Använd monospace - Senaste filer + Senaste filerna Storlek för typsnitt Benämning för anslutningen Radnummer - Wrap content - View it on the web - File - Folder - Light Theme - Go to Line… - Go to Page… - Find - Replace - Share - Keyboard suggestions and Swipe - Auto-Encoding - Set as the working folder - This is the working folder - Do you want to save the changes to the file %s? - Regular Expression - Text to find - Text to replace - Next - Previous - Please wait… - %s occurrences was found + Linda in innehåll + Kolla på det i webbläsaren + Fil + Mapp + Ljust Tema + Gå Till Linje… + Gå Till Sida… + Hitta + Byt Ut + Dela + Tangentbordsförslag och Swipe + Auto-Kodning + Sätt som nuvarande mapp + Det här är den nuvarande mappen + Vill du spara ändringarna till filen %s? + Reguljära uttryck + Text att hitta + Text som ska ersätta + Nästa + Förra + Var god vänta… + %s träffar hittade v%s - Translate - Changelog - Match case - Long click for more options - Auto save - Read only - Send error reports - Extra options - Split the text if too long - Ignore back button - Donate + Översätt + Ändringar + Matcha stor/liten bokstav + Långtryck för fler inställningar + Autospara + Läs endast läge + Skicka felrapport + Extra inställningar + Dela upp texten om den är för lång + Ignorera Tillbakaknappen + Donera Encoding - Share + Dela Info Turbo Editor - Preferences - Save - Syntax highlight - Undo - Redo - Open - The file %1$s was saved with success! - Open a file - No - New file + Inställningar + Spara + Syntax Markering + Ångra + Återställ + Öppna + Filen %1$s sparades! + Öppna en fil + Nej + Ny fil diff --git a/libraries/sharedCode/src/main/res/values-sv-rSE/strings_dialogs.xml b/libraries/sharedCode/src/main/res/values-sv-rSE/strings_dialogs.xml index ad64876..56411c1 100644 --- a/libraries/sharedCode/src/main/res/values-sv-rSE/strings_dialogs.xml +++ b/libraries/sharedCode/src/main/res/values-sv-rSE/strings_dialogs.xml @@ -19,16 +19,16 @@ ~ along with this program. If not, see . --> - Close - About + Stäng + Om open source app. + Turbo Editor är en gratis och öppen källkod app. Copyright 2013-2014 Vlad Mihalachi. All Rights Reserved.

- Many thanks to all who - helped with translations or - donated to me.
+ Många tack till alla som + hjälpt med översättningar eller + donerat.

- If you want to send feedback here is the XDA thread + Om du vill skicka feedback är detta XDA Tråden ]]>
diff --git a/libraries/sharedCode/src/main/res/values-sv-rSE/strings_donation.xml b/libraries/sharedCode/src/main/res/values-sv-rSE/strings_donation.xml deleted file mode 100644 index 9b2bcc8..0000000 --- a/libraries/sharedCode/src/main/res/values-sv-rSE/strings_donation.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - Donate - Donate to developer - open source app. - You can show your appreciation and support development by donating: - ]]> - You\'ve donated for this item already. - An ice cream - Cup of coffee - Electricity bills - The right pillow - Solid-state drive - Sound system - Failed to setup in-app-billing service! - Notice that Google is not responsible for that payments method. - diff --git a/libraries/sharedCode/src/main/res/values-tr-rTR/strings_dialogs.xml b/libraries/sharedCode/src/main/res/values-tr-rTR/strings_dialogs.xml index a90ae36..ee3095f 100644 --- a/libraries/sharedCode/src/main/res/values-tr-rTR/strings_dialogs.xml +++ b/libraries/sharedCode/src/main/res/values-tr-rTR/strings_dialogs.xml @@ -21,13 +21,10 @@ Kapat Hakkında - açık kaynak bir uygulamadır. + açık kaynak bir uygulamadır. Telif hakkı 2013-2014 Vlad Mihalachi. Tüm Hakları Saklıdır.

- Tüm çevirileriyle - veya bağışlarıyla yardımcı olanlara çok teşekkürler.
+ Tüm çevirileriyle veya bağışlarıyla yardımcı olanlara çok teşekkürler.

- Geri bildirim göndermek istiyorsanız XDA konusunu kullanabilirsiniz - ]]>
+ Geri bildirim göndermek istiyorsanız XDA konusunu kullanabilirsiniz]]>
diff --git a/libraries/sharedCode/src/main/res/values-tr-rTR/strings_donation.xml b/libraries/sharedCode/src/main/res/values-tr-rTR/strings_donation.xml index d6e4c1f..141cee0 100644 --- a/libraries/sharedCode/src/main/res/values-tr-rTR/strings_donation.xml +++ b/libraries/sharedCode/src/main/res/values-tr-rTR/strings_donation.xml @@ -26,8 +26,8 @@ Bağış yaparak gelişimini destekleyebilir ve beğeninizi gösterebilirsiniz: ]]>
Zaten bu öğe için bağış yaptınız. - Bir dondurma - Bir fincan kahve + Dondurma + Kahve Elektrik faturaları Ortopedik yastık Solid-state sürücü diff --git a/libraries/sharedCode/src/main/res/values-uk-rUA/strings.xml b/libraries/sharedCode/src/main/res/values-uk-rUA/strings.xml index ba3c203..c0500a1 100644 --- a/libraries/sharedCode/src/main/res/values-uk-rUA/strings.xml +++ b/libraries/sharedCode/src/main/res/values-uk-rUA/strings.xml @@ -20,57 +20,57 @@ --> - Use monospace - Recent files - Font size - Connection Name - Line Numbers - Wrap content - View it on the web - File - Folder - Light Theme - Go to Line… - Go to Page… - Find - Replace - Share - Keyboard suggestions and Swipe - Auto-Encoding - Set as the working folder - This is the working folder - Do you want to save the changes to the file %s? - Regular Expression - Text to find - Text to replace - Next - Previous - Please wait… - %s occurrences was found + Моноширний шрифт + Нещодавні файли + Розмір шрифту + Назва з\'єднання + Нумерація рядків + Перенесення рядків + Переглянути в броузері + Файл + Папка + Світла тема + Перейти на рядок… + Перейти на сторінку… + Пошук + Замінити + Поділитись + Клавіатурні підказки і свайп + Автоматичне кодування + Встановити як робочу папку + Це робоча папка + Зберегти зміни у файлі %s? + Регулярний вираз + Текст для пошуку + Текст для заміни + Далі + Назад + Будь ласка, зачекайте… + Знайдено %s v%s - Translate - Changelog - Match case - Long click for more options - Auto save - Read only - Send error reports - Extra options - Split the text if too long - Ignore back button - Donate - Encoding - Share - Info + Перекласти + Історія змін + Враховувати регістр + Утримуйте для додаткових опцій + Автоматичне збереження + Тільки для читання + Відправляти звіти про помилки + Додаткові опції + Розділення тексту, якщо занадто довгий + Ігнорувати кнопку Назад + Пожертвувати + Кодування + Поділитись + Інформація Turbo Editor - Preferences - Save - Syntax highlight - Undo - Redo - Open - The file %1$s was saved with success! - Open a file - No - New file + Налаштування + Зберегти + Підсвітка синтаксису + Скасувати + Повторити + Відкрити + Файл %1$s було успішно збережено! + Відкрити файл + Ні + Новий файл diff --git a/libraries/sharedCode/src/main/res/values-uk-rUA/strings_dialogs.xml b/libraries/sharedCode/src/main/res/values-uk-rUA/strings_dialogs.xml index ad64876..8a45f35 100644 --- a/libraries/sharedCode/src/main/res/values-uk-rUA/strings_dialogs.xml +++ b/libraries/sharedCode/src/main/res/values-uk-rUA/strings_dialogs.xml @@ -1,5 +1,4 @@ - + + + - Close - About + Закрити + Про програму open source app. + Turbo Editor це безкоштовна програма з відкритим вихідним кодом. Copyright 2013-2014 Vlad Mihalachi. All Rights Reserved.

- Many thanks to all who - helped with translations or - donated to me.
+ Велике спасибі всім хто + допомагає з перекладами або + підтримує мене

- If you want to send feedback here is the XDA thread + Зворотній зв\'язок тема на XDA ]]>
diff --git a/libraries/sharedCode/src/main/res/values-uk-rUA/strings_donation.xml b/libraries/sharedCode/src/main/res/values-uk-rUA/strings_donation.xml index 9b2bcc8..9c85e10 100644 --- a/libraries/sharedCode/src/main/res/values-uk-rUA/strings_donation.xml +++ b/libraries/sharedCode/src/main/res/values-uk-rUA/strings_donation.xml @@ -19,19 +19,19 @@ ~ along with this program. If not, see . --> - Donate - Donate to developer + Пожертвувати + Пожертва розробнику open source app. - You can show your appreciation and support development by donating: + Turbo Editor це безкоштовна програма з відкритим вихідним кодом. + Ви можете показати вашу вдячність і підтримати проект пожертвами: ]]> - You\'ve donated for this item already. - An ice cream - Cup of coffee - Electricity bills - The right pillow - Solid-state drive - Sound system - Failed to setup in-app-billing service! - Notice that Google is not responsible for that payments method. + Ви вже пожертвували. + Морозиво + Чашка кави + Рахунки за електрику + Хорошу подушку + SSD диск + Аудіо систему + Не вдалося виконати in-app-billing сервіс! + Зверніть увагу, що Google не відповідає за цей метод платежу. diff --git a/libraries/sharedCode/src/main/res/values/ids.xml b/libraries/sharedCode/src/main/res/values/ids.xml index c549bfe..de50092 100644 --- a/libraries/sharedCode/src/main/res/values/ids.xml +++ b/libraries/sharedCode/src/main/res/values/ids.xml @@ -28,6 +28,8 @@ + + @@ -46,6 +48,7 @@ + @@ -62,6 +65,7 @@ + diff --git a/libraries/sharedCode/src/main/res/values/strings.xml b/libraries/sharedCode/src/main/res/values/strings.xml index 72871dc..11ca75a 100644 --- a/libraries/sharedCode/src/main/res/values/strings.xml +++ b/libraries/sharedCode/src/main/res/values/strings.xml @@ -64,6 +64,7 @@ Turbo Editor Preferences Save + Save as Syntax highlight Undo Redo @@ -72,4 +73,6 @@ Open a file No New file + Delete current file + Replace all