Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
78407c292a | |||
4d26fa7f3d | |||
4b16119b53 | |||
bf4dcd51b8 | |||
e52a3cb9f5 | |||
5702a6c24f | |||
ffcd50616e | |||
46842a5343 | |||
df5a302129 | |||
04faa104ed | |||
a20f93f0f6 | |||
564e55385f | |||
2c62965a02 | |||
eaab21069b | |||
2dbab5220a | |||
520c4c53c0 | |||
2fefb3963c | |||
e0eb01168e | |||
30294f72b5 | |||
ed621d369e | |||
6507331360 | |||
ec4742149b | |||
97dd211dc2 | |||
fc67e5930e | |||
44d4a2828b |
5
.gitignore
vendored
5
.gitignore
vendored
@ -11,6 +11,7 @@
|
|||||||
# Generated files
|
# Generated files
|
||||||
bin/
|
bin/
|
||||||
gen/
|
gen/
|
||||||
|
doc/
|
||||||
|
|
||||||
# Proguard folder generated by Eclipse
|
# Proguard folder generated by Eclipse
|
||||||
proguard/
|
proguard/
|
||||||
@ -18,8 +19,6 @@ proguard/
|
|||||||
# Log Files
|
# Log Files
|
||||||
*.log
|
*.log
|
||||||
|
|
||||||
app-pro/
|
|
||||||
|
|
||||||
# Built application files
|
# Built application files
|
||||||
/*/build/
|
/*/build/
|
||||||
|
|
||||||
@ -59,3 +58,5 @@ local.properties
|
|||||||
.Trashes
|
.Trashes
|
||||||
ehthumbs.db
|
ehthumbs.db
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
*~
|
||||||
|
#*#
|
174
.idea/codeStyleSettings.xml
generated
Normal file
174
.idea/codeStyleSettings.xml
generated
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectCodeStyleSettingsManager">
|
||||||
|
<option name="PER_PROJECT_SETTINGS">
|
||||||
|
<value>
|
||||||
|
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
||||||
|
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
||||||
|
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
|
||||||
|
<value />
|
||||||
|
</option>
|
||||||
|
<option name="IMPORT_LAYOUT_TABLE">
|
||||||
|
<value>
|
||||||
|
<package name="android" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="com" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="junit" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="net" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="org" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="java" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="javax" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="" withSubpackages="true" static="true" />
|
||||||
|
<emptyLine />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="RIGHT_MARGIN" value="100" />
|
||||||
|
<AndroidXmlCodeStyleSettings>
|
||||||
|
<option name="USE_CUSTOM_SETTINGS" value="true" />
|
||||||
|
</AndroidXmlCodeStyleSettings>
|
||||||
|
<XML>
|
||||||
|
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
||||||
|
</XML>
|
||||||
|
<codeStyleSettings language="XML">
|
||||||
|
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||||
|
</indentOptions>
|
||||||
|
<arrangement>
|
||||||
|
<rules>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>xmlns:android</NAME>
|
||||||
|
<XML_NAMESPACE>Namespace:</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>xmlns:.*</NAME>
|
||||||
|
<XML_NAMESPACE>Namespace:</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:id</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:name</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>name</NAME>
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>style</NAME>
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:layout_width</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:layout_height</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:layout_.*</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:width</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:height</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</rules>
|
||||||
|
</arrangement>
|
||||||
|
</codeStyleSettings>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default (1)" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
|
|
5
.idea/inspectionProfiles/Project_Default.xml
generated
5
.idea/inspectionProfiles/Project_Default.xml
generated
@ -4,6 +4,11 @@
|
|||||||
<option name="myLocal" value="false" />
|
<option name="myLocal" value="false" />
|
||||||
<inspection_tool class="AndroidLintMissingQuantity" enabled="false" level="ERROR" enabled_by_default="false" />
|
<inspection_tool class="AndroidLintMissingQuantity" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||||
<inspection_tool class="AndroidLintMissingTranslation" enabled="false" level="ERROR" enabled_by_default="false" />
|
<inspection_tool class="AndroidLintMissingTranslation" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="AndroidLintNewApi" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||||
<inspection_tool class="AndroidLintUnusedQuantity" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="AndroidLintUnusedQuantity" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
|
||||||
|
<option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
|
||||||
|
<option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
|
||||||
|
</inspection_tool>
|
||||||
</profile>
|
</profile>
|
||||||
</component>
|
</component>
|
36
README.md
36
README.md
@ -1,38 +1,32 @@
|
|||||||
# Turbo Editor
|
# Turbo Editor
|
||||||
[](https://crowdin.com/project/turbo-client)
|
[](https://crowdin.com/project/turbo-client)
|
||||||
|
|
||||||
Simple, powerful and Open Source file editor for Android licensed under the GPLv3 license.
|
Simple, powerful and Open Source text editor for Android licensed under the GPLv3 license.
|
||||||
|
|
||||||
|
### Download
|
||||||
|
[](http://play.google.com/store/apps/details?id=com.maskyn.fileeditorpro)
|
||||||
|
|
||||||
|
[](https://f-droid.org/repository/browse/?fdid=com.maskyn.fileeditorpro)
|
||||||
|
|
||||||
### Contribute
|
### Contribute
|
||||||
You can contribute to this project in many ways:
|
You can contribute to this project in many ways:
|
||||||
* Browse our issues, comment on proposals, report bugs.
|
* Browse our issues, comment on proposals, report bugs.
|
||||||
* Clone the balanced-dashboard repo, make some changes according to our
|
|
||||||
development guidelines and issue a pull-request with your changes.
|
|
||||||
* Help to translate the application on [Crowdin][crowdin]
|
* Help to translate the application on [Crowdin][crowdin]
|
||||||
* [Donate][donate]
|
* Be a part of the Google Plus [Community][community googleplus]
|
||||||
|
* Discuss with us on [XDA thread][xda thread]
|
||||||
------
|
* Help to maintain this project active and [Donate][donate]
|
||||||
|
|
||||||
### Development guidelines
|
|
||||||
1. Fork it (`git clone git://github.com/vmihalachi/turbo-editor.git`)
|
|
||||||
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
||||||
3. Write your code
|
|
||||||
4. Commit your changes (`git commit -am 'Add some feature'`)
|
|
||||||
5. Push to the branch (`git push origin my-new-feature`)
|
|
||||||
6. Create new [pull request](https://help.github.com/articles/using-pull-requests)
|
|
||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
###Donate
|
###Donate
|
||||||
* Make a [Paypal][donate paypal] donation
|
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=26VWS2TSAMUJA)
|
||||||
* Flattr this project [](https://flattr.com/submit/auto?user_id=vmihalachi&url=https://raw.github.com/vmihalachi/turbo-editor&title=Turbo Editor&language=&tags=github&category=software)
|
|
||||||
|
[](https://flattr.com/submit/auto?user_id=vmihalachi&url=https://github.com/vmihalachi/turbo-editor&title=Turbo Editor&language=java&tags=github&category=software)
|
||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
###Download
|
###Images
|
||||||
* From the [Play Store][download playstore]
|

|
||||||
* Want to try beta releases? Be a part of the Google Plus [Community][community googleplus]!
|
|
||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
### Developer
|
### Developer
|
||||||
@ -56,8 +50,8 @@ See the [LICENSE][license] file that accompanies this distribution for the full
|
|||||||
[license]: https://github.com/vmihalachi/turbo-editor/LICENSE
|
[license]: https://github.com/vmihalachi/turbo-editor/LICENSE
|
||||||
[donate]: https://github.com/vmihalachi/turbo-editor#donate
|
[donate]: https://github.com/vmihalachi/turbo-editor#donate
|
||||||
[donate paypal]: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=PUQXSX6MTXHZ2
|
[donate paypal]: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=PUQXSX6MTXHZ2
|
||||||
|
[xda thread]: http://forum.xda-developers.com/android/apps-games/app-turbo-editor-text-editor-t2832016
|
||||||
[community googleplus]: https://plus.google.com/u/0/communities/111974095419108178946
|
[community googleplus]: https://plus.google.com/u/0/communities/111974095419108178946
|
||||||
[download playstore]: https://play.google.com/store/apps/details?id=com.maskyn.fileeditor
|
|
||||||
[crowdin]: https://crowdin.net/project/turbo-client
|
[crowdin]: https://crowdin.net/project/turbo-client
|
||||||
[developer site]: http://vmihalachi.com/
|
[developer site]: http://vmihalachi.com/
|
||||||
[crowdin]: https://crowdin.net/project/turbo-client
|
[crowdin]: https://crowdin.net/project/turbo-client
|
||||||
|
1
app-pro/.gitignore
vendored
Normal file
1
app-pro/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/build
|
56
app-pro/build.gradle
Normal file
56
app-pro/build.gradle
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 21
|
||||||
|
buildToolsVersion '21.0.2'
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "com.maskyn.fileeditorpro"
|
||||||
|
minSdkVersion 11
|
||||||
|
targetSdkVersion 21
|
||||||
|
versionCode 31
|
||||||
|
versionName "1.12"
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_7
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_7
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
runProguard false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lintOptions {
|
||||||
|
abortOnError false
|
||||||
|
}
|
||||||
|
packagingOptions {
|
||||||
|
exclude 'META-INF/LICENSE.txt'
|
||||||
|
exclude 'META-INF/NOTICE.txt'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
compile project(':libraries:sharedCode')
|
||||||
|
}
|
17
app-pro/proguard-rules.pro
vendored
Normal file
17
app-pro/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# By default, the flags in this file are appended to flags specified
|
||||||
|
# in C:/Users/Vlad/AppData/Local/Android/android-sdk/tools/proguard/proguard-android.txt
|
||||||
|
# You can edit the include path and order by changing the proguardFiles
|
||||||
|
# directive in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# Add any project specific keep options here:
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
@ -17,15 +17,16 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sharedcode.turboeditor.util;
|
package com.maskyn.fileeditorpro;
|
||||||
|
|
||||||
import android.widget.ScrollView;
|
import android.app.Application;
|
||||||
|
import android.test.ApplicationTestCase;
|
||||||
|
|
||||||
import sharedcode.turboeditor.views.GoodScrollView;
|
/**
|
||||||
|
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||||
public interface EditorInterface {
|
*/
|
||||||
public GoodScrollView getVerticalScrollView();
|
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||||
public String getFilePath();
|
public ApplicationTest() {
|
||||||
public PageSystem getPageSystem();
|
super(Application.class);
|
||||||
public void updateTextSyntax();
|
}
|
||||||
}
|
}
|
120
app-pro/src/main/AndroidManifest.xml
Normal file
120
app-pro/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<!--
|
||||||
|
~ 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 <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.maskyn.fileeditorpro"
|
||||||
|
android:installLocation="auto">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
|
||||||
|
|
||||||
|
<supports-screens
|
||||||
|
android:anyDensity="true"
|
||||||
|
android:largeScreens="true"
|
||||||
|
android:normalScreens="true"
|
||||||
|
android:resizeable="true"
|
||||||
|
android:smallScreens="true"
|
||||||
|
android:xlargeScreens="true" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
|
android:label="@string/nome_app_turbo_editor"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
android:largeHeap="true"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:name="sharedcode.turboeditor.activity.MyApp"
|
||||||
|
>
|
||||||
|
|
||||||
|
<!-- android:alwaysRetainTaskState="true" -->
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".HomeActivity"
|
||||||
|
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:windowSoftInputMode="stateUnspecified|adjustResize"
|
||||||
|
android:theme="@style/AppThemeEditorDark">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<action android:name="android.intent.action.EDIT" />
|
||||||
|
<action android:name="android.intent.action.PICK" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data android:scheme="file" />
|
||||||
|
<data android:mimeType="text/*" />
|
||||||
|
<data android:pathPattern="*.txt" />
|
||||||
|
<data android:pathPattern="*.html" />
|
||||||
|
<data android:pathPattern="*.css" />
|
||||||
|
<data android:pathPattern="*.js" />
|
||||||
|
<data android:pathPattern="*.md"/>
|
||||||
|
<data android:pathPattern="*.php" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="text/plain" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name="sharedcode.turboeditor.activity.SelectFileActivity"
|
||||||
|
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||||
|
android:label="@string/open_a_file"
|
||||||
|
android:parentActivityName=".HomeActivity"
|
||||||
|
android:theme="@style/AppThemeBaseLight">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
|
android:value=".HomeActivity" />
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="sharedcode.turboeditor.preferences.ExtraSettingsActivity"
|
||||||
|
android:label="@string/extra_options"
|
||||||
|
android:parentActivityName=".HomeActivity">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
|
android:value=".HomeActivity" />
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="com.sec.android.support.multiwindow"
|
||||||
|
android:value="true" />
|
||||||
|
<meta-data
|
||||||
|
android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W"
|
||||||
|
android:value="632.0dip" />
|
||||||
|
<meta-data
|
||||||
|
android:name="com.sec.android.multiwindow.DEFAULT_SIZE_H"
|
||||||
|
android:value="598.0dip" />
|
||||||
|
<meta-data
|
||||||
|
android:name="com.sec.android.multiwindow.MINIMUM_SIZE_W"
|
||||||
|
android:value="632.0dip" />
|
||||||
|
<meta-data
|
||||||
|
android:name="com.sec.android.multiwindow.MINIMUM_SIZE_H"
|
||||||
|
android:value="598.0dip" />
|
||||||
|
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
@ -17,9 +17,16 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sharedcode.turboeditor.util;
|
package com.maskyn.fileeditorpro;
|
||||||
|
|
||||||
public class Constants {
|
import android.os.Bundle;
|
||||||
public static final int MAX_FILE_SIZE = 20_000;
|
|
||||||
public static final boolean FOR_AMAZON = false;
|
import sharedcode.turboeditor.activity.BaseHomeActivity;
|
||||||
|
|
||||||
|
public class HomeActivity extends BaseHomeActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void displayInterstitial() {
|
||||||
|
// nothing to do here
|
||||||
|
}
|
||||||
}
|
}
|
@ -19,33 +19,35 @@
|
|||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
maven { url 'http://download.crashlytics.com/maven' }
|
mavenCentral()
|
||||||
|
maven { url 'https://maven.fabric.io/repo' }
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.crashlytics.tools.gradle:crashlytics-gradle:1.+'
|
classpath 'io.fabric.tools:gradle:1.+'
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'crashlytics'
|
apply plugin: 'io.fabric'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven { url 'http://download.crashlytics.com/maven' }
|
mavenCentral()
|
||||||
|
maven { url 'https://maven.fabric.io/repo' }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 20
|
compileSdkVersion 21
|
||||||
buildToolsVersion "20.0.0"
|
buildToolsVersion '21.0.2'
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.maskyn.fileeditor"
|
applicationId "com.maskyn.fileeditor"
|
||||||
minSdkVersion 14
|
minSdkVersion 11
|
||||||
targetSdkVersion 20
|
targetSdkVersion 21
|
||||||
versionCode 26
|
versionCode 31
|
||||||
versionName "1.10"
|
versionName "1.13"
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_7
|
sourceCompatibility JavaVersion.VERSION_1_7
|
||||||
@ -57,12 +59,20 @@ android {
|
|||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lintOptions {
|
||||||
|
abortOnError false
|
||||||
|
}
|
||||||
|
packagingOptions {
|
||||||
|
exclude 'META-INF/LICENSE.txt'
|
||||||
|
exclude 'META-INF/NOTICE.txt'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile fileTree(dir: 'libs', include: '*.jar')
|
compile fileTree(dir: 'libs', include: '*.jar')
|
||||||
compile project(':libraries:sharedCode')
|
compile project(':libraries:sharedCode')
|
||||||
compile 'com.google.android.gms:play-services:5.0.89'
|
compile 'com.google.android.gms:play-services:6.1.11'
|
||||||
compile 'com.crashlytics.android:crashlytics:1.+'
|
compile('com.crashlytics.sdk.android:crashlytics:2.+@aar') {
|
||||||
|
transitive = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
|
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="com.android.vending.BILLING" />
|
||||||
|
|
||||||
<supports-screens
|
<supports-screens
|
||||||
android:anyDensity="true"
|
android:anyDensity="true"
|
||||||
@ -39,9 +40,10 @@
|
|||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
android:label="@string/nome_app_turbo_editor"
|
android:label="@string/nome_app_turbo_editor"
|
||||||
android:hardwareAccelerated="false"
|
android:hardwareAccelerated="true"
|
||||||
android:largeHeap="true"
|
android:largeHeap="true"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
|
android:name="sharedcode.turboeditor.activity.MyApp"
|
||||||
>
|
>
|
||||||
|
|
||||||
<!-- android:alwaysRetainTaskState="true" -->
|
<!-- android:alwaysRetainTaskState="true" -->
|
||||||
@ -52,8 +54,8 @@
|
|||||||
android:name=".HomeActivity"
|
android:name=".HomeActivity"
|
||||||
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
|
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:windowSoftInputMode="stateUnspecified|adjustPan"
|
android:windowSoftInputMode="stateUnspecified|adjustResize"
|
||||||
android:theme="@style/AppTheme.Light.Editor">
|
android:theme="@style/AppThemeEditorDark">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
@ -83,35 +85,24 @@
|
|||||||
<data android:mimeType="text/plain" />
|
<data android:mimeType="text/plain" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
|
||||||
android:name="sharedcode.turboeditor.activity.PreferenceAbout"
|
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
|
||||||
android:label="@string/info"
|
|
||||||
android:parentActivityName=".HomeActivity"
|
|
||||||
android:theme="@style/AppTheme.Dark">
|
|
||||||
<meta-data
|
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
|
||||||
android:value="com.maskyn.fileeditor.activity.HomeActivity" />
|
|
||||||
</activity>
|
|
||||||
<activity
|
|
||||||
android:name="sharedcode.turboeditor.activity.LicensesActivity"
|
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
|
||||||
android:label="@string/open_source_license"
|
|
||||||
android:parentActivityName="sharedcode.turboeditor.activity.PreferenceAbout"
|
|
||||||
android:theme="@style/AppTheme.Light">
|
|
||||||
<meta-data
|
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
|
||||||
android:value="com.maskyn.fileeditor.activity.PreferenceAbout" />
|
|
||||||
</activity>
|
|
||||||
<activity
|
<activity
|
||||||
android:name="sharedcode.turboeditor.activity.SelectFileActivity"
|
android:name="sharedcode.turboeditor.activity.SelectFileActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||||
android:label="@string/open_a_file"
|
android:label="@string/open_a_file"
|
||||||
android:parentActivityName=".HomeActivity"
|
android:parentActivityName=".HomeActivity"
|
||||||
android:theme="@style/AppTheme.Light">
|
android:theme="@style/AppThemeBaseLight">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value="com.maskyn.fileeditor.activity.HomeActivity" />
|
android:value=".HomeActivity" />
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="sharedcode.turboeditor.preferences.ExtraSettingsActivity"
|
||||||
|
android:label="@string/extra_options"
|
||||||
|
android:parentActivityName=".HomeActivity">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
|
android:value=".HomeActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
package com.maskyn.fileeditor;
|
package com.maskyn.fileeditor;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
import com.google.android.gms.ads.AdRequest;
|
import com.google.android.gms.ads.AdRequest;
|
||||||
import com.google.android.gms.ads.InterstitialAd;
|
import com.google.android.gms.ads.InterstitialAd;
|
||||||
|
|
||||||
@ -28,32 +30,21 @@ import java.util.Calendar;
|
|||||||
import sharedcode.turboeditor.preferences.PreferenceHelper;
|
import sharedcode.turboeditor.preferences.PreferenceHelper;
|
||||||
|
|
||||||
public class AdsHelper {
|
public class AdsHelper {
|
||||||
private Activity activity;
|
|
||||||
private InterstitialAd interstitial;
|
private InterstitialAd interstitial;
|
||||||
|
|
||||||
public AdsHelper(Activity activity) {
|
public AdsHelper(Activity activity) {
|
||||||
this.activity = activity;
|
|
||||||
int today = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
|
|
||||||
int lastDayAdShowed = PreferenceHelper.getLastDayAdShowed(activity);
|
|
||||||
boolean showAd = today != lastDayAdShowed;
|
|
||||||
if (showAd) {
|
|
||||||
|
|
||||||
interstitial = new InterstitialAd(activity);
|
interstitial = new InterstitialAd(activity);
|
||||||
interstitial.setAdUnitId("ca-app-pub-5679083452234719/7178038180");
|
interstitial.setAdUnitId("ca-app-pub-5679083452234719/7178038180");
|
||||||
|
|
||||||
// Create ad request.
|
// Create ad request.
|
||||||
AdRequest adRequest = new AdRequest.Builder().build();
|
AdRequest adRequest = new AdRequest.Builder().build();
|
||||||
|
|
||||||
// Begin loading your interstitial.
|
// Begin loading your interstitial.
|
||||||
interstitial.loadAd(adRequest);
|
interstitial.loadAd(adRequest);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void displayInterstitial() {
|
public void displayInterstitial() {
|
||||||
if (interstitial != null && interstitial.isLoaded()) {
|
interstitial.show();
|
||||||
interstitial.show();
|
|
||||||
int today = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
|
|
||||||
PreferenceHelper.setLastDayAdShowed(activity, today);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,11 @@ package com.maskyn.fileeditor;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import com.crashlytics.android.Crashlytics;
|
import com.crashlytics.android.Crashlytics;
|
||||||
|
|
||||||
|
import io.fabric.sdk.android.Fabric;
|
||||||
import sharedcode.turboeditor.activity.BaseHomeActivity;
|
import sharedcode.turboeditor.activity.BaseHomeActivity;
|
||||||
import sharedcode.turboeditor.preferences.PreferenceHelper;
|
import sharedcode.turboeditor.preferences.PreferenceHelper;
|
||||||
|
import sharedcode.turboeditor.util.ProCheckUtils;
|
||||||
|
|
||||||
public class HomeActivity extends BaseHomeActivity {
|
public class HomeActivity extends BaseHomeActivity {
|
||||||
|
|
||||||
@ -34,13 +37,15 @@ public class HomeActivity extends BaseHomeActivity {
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
if(PreferenceHelper.getSendErrorReports(this))
|
if(PreferenceHelper.getSendErrorReports(this))
|
||||||
Crashlytics.start(this);
|
Fabric.with(this, new Crashlytics());
|
||||||
// setup the ads
|
// setup the ads
|
||||||
adsHelper = new AdsHelper(this);
|
if(!ProCheckUtils.isPro(this))
|
||||||
|
adsHelper = new AdsHelper(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void displayInterstitial() {
|
public void displayInterstitial() {
|
||||||
adsHelper.displayInterstitial();
|
if(adsHelper != null && !ProCheckUtils.isPro(this))
|
||||||
|
adsHelper.displayInterstitial();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ buildscript {
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:0.12.+'
|
classpath 'com.android.tools.build:gradle:0.13.+'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
@ -1,30 +1,209 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
|
||||||
~ 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 <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<pre-dex-items>
|
<pre-dex-items>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\eventbus-2.2.1-32e81c5612ed132ff771b5425053d87f4f6c68c5.jar"
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\commons-io-2.4-63b64e68cd19031cd252ac65a3ef94421c1bf0f4.jar"
|
||||||
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\de.greenrobot\eventbus\2.2.1\a18ff12a9ab5ae52fd30d42f134517997568231e\eventbus-2.2.1.jar"
|
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\commons-io\commons-io\2.4\b1b6ea3b7e4aa4f492509a4952029cd8e48019ad\commons-io-2.4.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="b1b6ea3b7e4aa4f492509a4952029cd8e48019ad"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\pre-dexed\release\classes-4dd6beddde59ff8bd6c22bd0d65ac974f7e489d2.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\exploded-aar\turbo-editor.libraries\sharedCode\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="4291d7fc866f70dc187c66c7063f806100c4d879"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\commons-io-2.4-63b64e68cd19031cd252ac65a3ef94421c1bf0f4.jar"
|
||||||
|
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\commons-io\commons-io\2.4\b1b6ea3b7e4aa4f492509a4952029cd8e48019ad\commons-io-2.4.jar"
|
||||||
jumboMode="false"
|
jumboMode="false"
|
||||||
revision="20.0.0"
|
revision="20.0.0"
|
||||||
|
sha1="b1b6ea3b7e4aa4f492509a4952029cd8e48019ad"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\release\classes-579a5ce52888f504a812e0f68758a11f20a21c15.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\exploded-aar\TurboMaterialEditor.libraries\sharedCode\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="a593d4ce7ccdfa1eac8d97a82db64f23614b59a1"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\pre-dexed\debug\classes-40c5f3698ba688207904eaae4b4b57dbf850297e.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\exploded-aar\com.crashlytics.sdk.android\answers\1.0.0\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="a8c73f3b98c2732c03ea09378ca322b56dea153a"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\commons-lang3-3.1-84728078c80f2c8637e0c3fe426ad61433c75bb6.jar"
|
||||||
|
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\org.apache.commons\commons-lang3\3.1\905075e6c80f206bbe6cf1e809d2caa69f420c76\commons-lang3-3.1.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="905075e6c80f206bbe6cf1e809d2caa69f420c76"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\pre-dexed\debug\classes-52b3d51bec6ecfeacbc105275c0e6a98b8869b1b.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\exploded-aar\com.crashlytics.sdk.android\crashlytics\2.0.0\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="832029c6f15447b2cb64ca4f8cf12172c9091857"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\pre-dexed\debug\classes-515446996fed08836a9331ef47b508a0383ffa22.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\exploded-aar\turbo-editor.libraries\RootCommands\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="e3bacad84e40c773d40010a5520810920887a920"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\classes-9b612f0cb16e63277808158fe971bb4f40c98d29.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\com.github.gabrielemariotti.changeloglib\library\1.5.1\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="74a89f0f8b56d9f11d70b8d8134cf4109f4797dc"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\pre-dexed\debug\support-v4-19.0.1-f87b13e7ed00736c2050eda75093bf42b0503c64.jar"
|
||||||
|
jar="C:\Users\Vlad\AppData\Local\Android\android-sdk\extras\android\m2repository\com\android\support\support-v4\19.0.1\support-v4-19.0.1.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="587da9a481ffd341d2fa091704489b89845ddacd"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\classes-c9a98cf79b48106440348a9fa210060d1b8b2647.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\exploded-aar\TurboMaterialEditor.libraries\RootCommands\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="cdecd8167dfb75d5785decb911fc4516445dd6a6"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\classes-2ad27a3265673aeeb8f40e4322d8e19509329c96.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\exploded-aar\com.github.gabrielemariotti.changeloglib\library\1.5.1\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="74a89f0f8b56d9f11d70b8d8134cf4109f4797dc"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\library-2.4.0-6b043a8574fb97c742ca3065362b2a29e8f870bc.jar"
|
||||||
|
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\com.nineoldandroids\library\2.4.0\e9b63380f3a242dbdbf103a2355ad7e43bad17cb\library-2.4.0.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="19.1.0"
|
||||||
|
sha1="e9b63380f3a242dbdbf103a2355ad7e43bad17cb"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\juniversalchardet-1.0.3-65b2b356e3f2da4b67e00aba70923d6321852204.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\sharedCode\unspecified\libs\juniversalchardet-1.0.3.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="591d72211acc0b909b79c840e0b3ed9a0982d807"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\classes-82d5b6cab7f16bad663de7c7008673037efb0e1b.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\FloatingActionButton\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="a1fbf4d4c1f1e1fe357b9ed1de15f4eea2217274"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\pre-dexed\debug\classes-7a329e7f23515542bf02d96773d08da1d2333a7b.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\exploded-aar\turbo-editor.libraries\FloatingActionButton\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="a1fbf4d4c1f1e1fe357b9ed1de15f4eea2217274"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\pre-dexed\debug\classes-d44090b77791e486eccbc4d8859b00a83623bf2b.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\exploded-aar\com.google.android.gms\play-services\6.1.11\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="0f700f6802ba1a1f1fa7ac26d5db0666a89d75a6"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\pre-dexed\debug\juniversalchardet-1.0.3-sources-436707958bb47977373cb4a2d842cdbf635fd840.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\exploded-aar\turbo-editor.libraries\sharedCode\unspecified\libs\juniversalchardet-1.0.3-sources.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="77979eaa98f90806f984155f44f63cc1fb60ac25"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\classes-30cc9565ecef1e8ae8577530d7ddd41993d192d7.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\RootCommands\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="85e7b55f468c5591965a5171179d3858b46822a9"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\classes-a8678f35ea62f18f2f7b60a15203aa6c74b5e559.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\exploded-aar\com.google.android.gms\play-services\5.0.89\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="d71573c9c5ea98a8db47ad6ff993a63d492b3bfa"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\juniversalchardet-1.0.3-sources-58cfedaebe3b94ec0eaa2ede4e66aae8dbe309b0.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\sharedCode\unspecified\libs\juniversalchardet-1.0.3-sources.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="19.1.0"
|
||||||
|
sha1="77979eaa98f90806f984155f44f63cc1fb60ac25"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\juniversalchardet-1.0.3-2e38d54a78dd518320bb6abe3d8931a19ff26792.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\exploded-aar\TurboMaterialEditor.libraries\sharedCode\unspecified\libs\juniversalchardet-1.0.3.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="591d72211acc0b909b79c840e0b3ed9a0982d807"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\classes-9b612f0cb16e63277808158fe971bb4f40c98d29.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\com.github.gabrielemariotti.changeloglib\library\1.5.1\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="19.1.0"
|
||||||
|
sha1="74a89f0f8b56d9f11d70b8d8134cf4109f4797dc"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\pre-dexed\debug\juniversalchardet-1.0.3-9db20cdcb8ae72104757d81297c98978c65bd91b.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\exploded-aar\turbo-editor.libraries\sharedCode\unspecified\libs\juniversalchardet-1.0.3.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="591d72211acc0b909b79c840e0b3ed9a0982d807"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\library-2.4.0-6b043a8574fb97c742ca3065362b2a29e8f870bc.jar"
|
||||||
|
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\com.nineoldandroids\library\2.4.0\e9b63380f3a242dbdbf103a2355ad7e43bad17cb\library-2.4.0.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="e9b63380f3a242dbdbf103a2355ad7e43bad17cb"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\commons-lang3-3.1-84728078c80f2c8637e0c3fe426ad61433c75bb6.jar"
|
||||||
|
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\org.apache.commons\commons-lang3\3.1\905075e6c80f206bbe6cf1e809d2caa69f420c76\commons-lang3-3.1.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="905075e6c80f206bbe6cf1e809d2caa69f420c76"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\commons-io-2.4-63b64e68cd19031cd252ac65a3ef94421c1bf0f4.jar"
|
||||||
|
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\commons-io\commons-io\2.4\b1b6ea3b7e4aa4f492509a4952029cd8e48019ad\commons-io-2.4.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="19.1.0"
|
||||||
|
sha1="b1b6ea3b7e4aa4f492509a4952029cd8e48019ad"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\pre-dexed\debug\classes-bfc447e4dbe83598b94dbdc8e38492cbbda6ebb2.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\exploded-aar\TurboMaterialEditor.libraries\RootCommands\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="cdecd8167dfb75d5785decb911fc4516445dd6a6"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\pre-dexed\debug\classes-91de6979bb6be1b46cde32b462c23831eadd01d4.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\exploded-aar\com.github.gabrielemariotti.changeloglib\library\1.5.1\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="74a89f0f8b56d9f11d70b8d8134cf4109f4797dc"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\library-2.4.0-6b043a8574fb97c742ca3065362b2a29e8f870bc.jar"
|
||||||
|
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\com.nineoldandroids\library\2.4.0\e9b63380f3a242dbdbf103a2355ad7e43bad17cb\library-2.4.0.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="e9b63380f3a242dbdbf103a2355ad7e43bad17cb"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\juniversalchardet-1.0.3-65b2b356e3f2da4b67e00aba70923d6321852204.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\sharedCode\unspecified\libs\juniversalchardet-1.0.3.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="19.1.0"
|
||||||
|
sha1="591d72211acc0b909b79c840e0b3ed9a0982d807"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\classes-9b612f0cb16e63277808158fe971bb4f40c98d29.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\com.github.gabrielemariotti.changeloglib\library\1.5.1\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="74a89f0f8b56d9f11d70b8d8134cf4109f4797dc"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\juniversalchardet-1.0.3-sources-58cfedaebe3b94ec0eaa2ede4e66aae8dbe309b0.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\sharedCode\unspecified\libs\juniversalchardet-1.0.3-sources.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="77979eaa98f90806f984155f44f63cc1fb60ac25"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\eventbus-2.2.1-32e81c5612ed132ff771b5425053d87f4f6c68c5.jar"
|
||||||
|
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\de.greenrobot\eventbus\2.2.1\a18ff12a9ab5ae52fd30d42f134517997568231e\eventbus-2.2.1.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="19.1.0"
|
||||||
sha1="a18ff12a9ab5ae52fd30d42f134517997568231e"/>
|
sha1="a18ff12a9ab5ae52fd30d42f134517997568231e"/>
|
||||||
<item
|
<item
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\pre-dexed\debug\juniversalchardet-1.0.3-24b647622164ce26bc5d0be361e05056efc68e13.jar"
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\pre-dexed\debug\juniversalchardet-1.0.3-24b647622164ce26bc5d0be361e05056efc68e13.jar"
|
||||||
@ -32,60 +211,12 @@
|
|||||||
jumboMode="false"
|
jumboMode="false"
|
||||||
revision="20.0.0"
|
revision="20.0.0"
|
||||||
sha1="591d72211acc0b909b79c840e0b3ed9a0982d807"/>
|
sha1="591d72211acc0b909b79c840e0b3ed9a0982d807"/>
|
||||||
<item
|
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\pre-dexed\debug\support-v4-19.0.1-f87b13e7ed00736c2050eda75093bf42b0503c64.jar"
|
|
||||||
jar="C:\Users\Vlad\AppData\Local\Android\android-sdk\extras\android\m2repository\com\android\support\support-v4\19.0.1\support-v4-19.0.1.jar"
|
|
||||||
jumboMode="false"
|
|
||||||
revision="20.0.0"
|
|
||||||
sha1="587da9a481ffd341d2fa091704489b89845ddacd"/>
|
|
||||||
<item
|
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\commons-io-2.4-63b64e68cd19031cd252ac65a3ef94421c1bf0f4.jar"
|
|
||||||
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\commons-io\commons-io\2.4\b1b6ea3b7e4aa4f492509a4952029cd8e48019ad\commons-io-2.4.jar"
|
|
||||||
jumboMode="false"
|
|
||||||
revision="20.0.0"
|
|
||||||
sha1="b1b6ea3b7e4aa4f492509a4952029cd8e48019ad"/>
|
|
||||||
<item
|
<item
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\classes-da434e33e14290126d2ad09adf85ad0bbd76f025.jar"
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\classes-da434e33e14290126d2ad09adf85ad0bbd76f025.jar"
|
||||||
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\exploded-aar\TurboMaterialEditor.libraries\FloatingActionButton\unspecified\classes.jar"
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\exploded-aar\TurboMaterialEditor.libraries\FloatingActionButton\unspecified\classes.jar"
|
||||||
jumboMode="false"
|
jumboMode="false"
|
||||||
revision="20.0.0"
|
revision="20.0.0"
|
||||||
sha1="2f3117da0016b1126fafe7fb332a45d2f910d76c"/>
|
sha1="2f3117da0016b1126fafe7fb332a45d2f910d76c"/>
|
||||||
<item
|
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\pre-dexed\debug\classes-a52f37b7ca7cde7ab02ff10bba80d1c496284125.jar"
|
|
||||||
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\exploded-aar\TurboMaterialEditor.libraries\FloatingActionButton\unspecified\classes.jar"
|
|
||||||
jumboMode="false"
|
|
||||||
revision="20.0.0"
|
|
||||||
sha1="2f3117da0016b1126fafe7fb332a45d2f910d76c"/>
|
|
||||||
<item
|
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\support-v4-19.1.0-cf7033c44b86e758f85990185111614bac3ecfa8.jar"
|
|
||||||
jar="C:\Users\Vlad\AppData\Local\Android\android-sdk\extras\android\m2repository\com\android\support\support-v4\19.1.0\support-v4-19.1.0.jar"
|
|
||||||
jumboMode="false"
|
|
||||||
revision="20.0.0"
|
|
||||||
sha1="85f201b380937e61a9dce6ca90ccf6872abbfb67"/>
|
|
||||||
<item
|
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\juniversalchardet-1.0.3-2e38d54a78dd518320bb6abe3d8931a19ff26792.jar"
|
|
||||||
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\exploded-aar\TurboMaterialEditor.libraries\sharedCode\unspecified\libs\juniversalchardet-1.0.3.jar"
|
|
||||||
jumboMode="false"
|
|
||||||
revision="20.0.0"
|
|
||||||
sha1="591d72211acc0b909b79c840e0b3ed9a0982d807"/>
|
|
||||||
<item
|
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\classes-2ad27a3265673aeeb8f40e4322d8e19509329c96.jar"
|
|
||||||
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\exploded-aar\com.github.gabrielemariotti.changeloglib\library\1.5.1\classes.jar"
|
|
||||||
jumboMode="false"
|
|
||||||
revision="20.0.0"
|
|
||||||
sha1="74a89f0f8b56d9f11d70b8d8134cf4109f4797dc"/>
|
|
||||||
<item
|
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\pre-dexed\debug\classes-bfc447e4dbe83598b94dbdc8e38492cbbda6ebb2.jar"
|
|
||||||
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\exploded-aar\TurboMaterialEditor.libraries\RootCommands\unspecified\classes.jar"
|
|
||||||
jumboMode="false"
|
|
||||||
revision="20.0.0"
|
|
||||||
sha1="cdecd8167dfb75d5785decb911fc4516445dd6a6"/>
|
|
||||||
<item
|
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\release\classes-579a5ce52888f504a812e0f68758a11f20a21c15.jar"
|
|
||||||
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\exploded-aar\TurboMaterialEditor.libraries\sharedCode\unspecified\classes.jar"
|
|
||||||
jumboMode="false"
|
|
||||||
revision="20.0.0"
|
|
||||||
sha1="a593d4ce7ccdfa1eac8d97a82db64f23614b59a1"/>
|
|
||||||
<item
|
<item
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\pre-dexed\debug\classes-0a2ec632e1127b260f2b888ca5539fd41a1a638b.jar"
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\pre-dexed\debug\classes-0a2ec632e1127b260f2b888ca5539fd41a1a638b.jar"
|
||||||
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\exploded-aar\com.github.gabrielemariotti.changeloglib\library\1.5.1\classes.jar"
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\exploded-aar\com.github.gabrielemariotti.changeloglib\library\1.5.1\classes.jar"
|
||||||
@ -93,17 +224,41 @@
|
|||||||
revision="20.0.0"
|
revision="20.0.0"
|
||||||
sha1="74a89f0f8b56d9f11d70b8d8134cf4109f4797dc"/>
|
sha1="74a89f0f8b56d9f11d70b8d8134cf4109f4797dc"/>
|
||||||
<item
|
<item
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\classes-a8678f35ea62f18f2f7b60a15203aa6c74b5e559.jar"
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\pre-dexed\debug\classes-33698a085ac2060587beda19b5b3900d3dffd1e7.jar"
|
||||||
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\exploded-aar\com.google.android.gms\play-services\5.0.89\classes.jar"
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\exploded-aar\com.android.support\support-v4\21.0.0\classes.jar"
|
||||||
jumboMode="false"
|
jumboMode="false"
|
||||||
revision="20.0.0"
|
revision="21.0.2"
|
||||||
sha1="d71573c9c5ea98a8db47ad6ff993a63d492b3bfa"/>
|
sha1="686344a780033e4ba22b926cd225f8d4941247e6"/>
|
||||||
<item
|
<item
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\pre-dexed\release\classes-3e47e18f46719c7bf296f4b49ff03aaa3d406ba6.jar"
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\support-v4-19.1.0-cf7033c44b86e758f85990185111614bac3ecfa8.jar"
|
||||||
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\exploded-aar\TurboMaterialEditor.libraries\sharedCode\unspecified\classes.jar"
|
jar="C:\Users\Vlad\AppData\Local\Android\android-sdk\extras\android\m2repository\com\android\support\support-v4\19.1.0\support-v4-19.1.0.jar"
|
||||||
jumboMode="false"
|
jumboMode="false"
|
||||||
revision="20.0.0"
|
revision="20.0.0"
|
||||||
sha1="a593d4ce7ccdfa1eac8d97a82db64f23614b59a1"/>
|
sha1="85f201b380937e61a9dce6ca90ccf6872abbfb67"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\pre-dexed\debug\internal_impl-21.0.0-74269e33561519e0fdabab9550f16a5986255be9.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\exploded-aar\com.android.support\support-v4\21.0.0\libs\internal_impl-21.0.0.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="1609e6d42d0480b0f4188e2c29f75388fa12a8f0"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\eventbus-2.2.1-32e81c5612ed132ff771b5425053d87f4f6c68c5.jar"
|
||||||
|
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\de.greenrobot\eventbus\2.2.1\a18ff12a9ab5ae52fd30d42f134517997568231e\eventbus-2.2.1.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="a18ff12a9ab5ae52fd30d42f134517997568231e"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\classes-30cc9565ecef1e8ae8577530d7ddd41993d192d7.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\RootCommands\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="e3bacad84e40c773d40010a5520810920887a920"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\classes-bcfe21eb1248db73c27c811996e28274cf39b024.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\sharedCode\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="19.1.0"
|
||||||
|
sha1="8203f36efafa2a6ef438b83fc86b9bdc469e7368"/>
|
||||||
<item
|
<item
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\release\crashlytics-1.1.13-7bbec76a44aa9cc3279ec6bff22b2c929a8abf67.jar"
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\release\crashlytics-1.1.13-7bbec76a44aa9cc3279ec6bff22b2c929a8abf67.jar"
|
||||||
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\com.crashlytics.android\crashlytics\1.1.13\e821eafa1bf489a26bdb71f95078c26785b37a1\crashlytics-1.1.13.jar"
|
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\com.crashlytics.android\crashlytics\1.1.13\e821eafa1bf489a26bdb71f95078c26785b37a1\crashlytics-1.1.13.jar"
|
||||||
@ -111,10 +266,106 @@
|
|||||||
revision="20.0.0"
|
revision="20.0.0"
|
||||||
sha1="0e821eafa1bf489a26bdb71f95078c26785b37a1"/>
|
sha1="0e821eafa1bf489a26bdb71f95078c26785b37a1"/>
|
||||||
<item
|
<item
|
||||||
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\classes-c9a98cf79b48106440348a9fa210060d1b8b2647.jar"
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\support-annotations-21.0.0-7b7e20ddbdfce40d4a29c1e68c2dbbc5bb512ab5.jar"
|
||||||
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\exploded-aar\TurboMaterialEditor.libraries\RootCommands\unspecified\classes.jar"
|
jar="C:\Users\Vlad\AppData\Local\Android\android-sdk\extras\android\m2repository\com\android\support\support-annotations\21.0.0\support-annotations-21.0.0.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="1a578b9607b36266c63d43a4fa0ab5664dbe911e"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\classes-fb4f15a411cfb0bffc51b68ad64a4794d3d67ae4.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\com.android.support\appcompat-v7\21.0.0\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="95fd37732ec852e99f07eeb516a3650172f1d136"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\classes-bcfe21eb1248db73c27c811996e28274cf39b024.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\sharedCode\unspecified\classes.jar"
|
||||||
jumboMode="false"
|
jumboMode="false"
|
||||||
revision="20.0.0"
|
revision="20.0.0"
|
||||||
sha1="cdecd8167dfb75d5785decb911fc4516445dd6a6"/>
|
sha1="991591ff9dbe9e472a47cf66fe6c120f89a68eaa"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\classes-82d5b6cab7f16bad663de7c7008673037efb0e1b.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\FloatingActionButton\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="19.1.0"
|
||||||
|
sha1="2e2f6526f3c5fb34230d14e52bdc24addb67ea9f"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\juniversalchardet-1.0.3-65b2b356e3f2da4b67e00aba70923d6321852204.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\sharedCode\unspecified\libs\juniversalchardet-1.0.3.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="591d72211acc0b909b79c840e0b3ed9a0982d807"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app\build\intermediates\pre-dexed\debug\eventbus-2.2.1-32e81c5612ed132ff771b5425053d87f4f6c68c5.jar"
|
||||||
|
jar="C:\Users\Vlad\.gradle\caches\modules-2\files-2.1\de.greenrobot\eventbus\2.2.1\a18ff12a9ab5ae52fd30d42f134517997568231e\eventbus-2.2.1.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="a18ff12a9ab5ae52fd30d42f134517997568231e"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\pre-dexed\debug\classes-e4e5a16633bd011fd3d270f1bcdf565f2bd9f2b3.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\exploded-aar\com.crashlytics.sdk.android\beta\1.0.0\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="068f232cbc319d814ad6ad01fd0ed0ac6d6c5414"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\pre-dexed\debug\classes-39edd57531ecc124992725bca5e8b42be236e3ec.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\exploded-aar\io.fabric.sdk.android\fabric\1.0.0\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="20a6dfbe395a3557a58a3d9f4460c15b0ce04d1e"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\pre-dexed\debug\classes-a52f37b7ca7cde7ab02ff10bba80d1c496284125.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\exploded-aar\TurboMaterialEditor.libraries\FloatingActionButton\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="2f3117da0016b1126fafe7fb332a45d2f910d76c"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\juniversalchardet-1.0.3-sources-58cfedaebe3b94ec0eaa2ede4e66aae8dbe309b0.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\sharedCode\unspecified\libs\juniversalchardet-1.0.3-sources.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="77979eaa98f90806f984155f44f63cc1fb60ac25"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\classes-82d5b6cab7f16bad663de7c7008673037efb0e1b.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\FloatingActionButton\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="df1a8540495d6724b8582db31fcdd49b04d8b707"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\classes-30cc9565ecef1e8ae8577530d7ddd41993d192d7.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\RootCommands\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="19.1.0"
|
||||||
|
sha1="cb3d22565863773944a8c15de408e864e34d6da1"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\pre-dexed\debug\classes-aa4ad551e94dc47c364b1b7f46bb2eb1b6ceed85.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app\build\intermediates\exploded-aar\com.android.support\appcompat-v7\21.0.0\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="95fd37732ec852e99f07eeb516a3650172f1d136"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\classes-e90e1f4e06d0f5aa27166f2f8f5fcea319efbd95.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\com.android.support\support-v4\21.0.0\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="686344a780033e4ba22b926cd225f8d4941247e6"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\release\classes-bcfe21eb1248db73c27c811996e28274cf39b024.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\turbo-editor.libraries\sharedCode\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="4291d7fc866f70dc187c66c7063f806100c4d879"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\pre-dexed\release\classes-3e47e18f46719c7bf296f4b49ff03aaa3d406ba6.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\TurboMaterialEditor\app-pro\build\intermediates\exploded-aar\TurboMaterialEditor.libraries\sharedCode\unspecified\classes.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="20.0.0"
|
||||||
|
sha1="a593d4ce7ccdfa1eac8d97a82db64f23614b59a1"/>
|
||||||
|
<item
|
||||||
|
dex="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\pre-dexed\debug\internal_impl-21.0.0-b15535acecaec42d04239e17e0a03ab072a43104.jar"
|
||||||
|
jar="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\app-pro\build\intermediates\exploded-aar\com.android.support\support-v4\21.0.0\libs\internal_impl-21.0.0.jar"
|
||||||
|
jumboMode="false"
|
||||||
|
revision="21.0.2"
|
||||||
|
sha1="1609e6d42d0480b0f4188e2c29f75388fa12a8f0"/>
|
||||||
|
|
||||||
</pre-dex-items>
|
</pre-dex-items>
|
||||||
|
Binary file not shown.
23
gradle/wrapper/gradle-wrapper.properties
vendored
23
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,25 +1,6 @@
|
|||||||
#
|
#Wed Oct 22 18:10:25 CEST 2014
|
||||||
# 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 <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
|
|
||||||
#Wed Apr 10 15:27:10 PDT 2013
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<manifest
|
<manifest
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.faizmalkani.floatingactionbutton">
|
package="com.faizmalkani.floatingactionbutton">
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 19
|
compileSdkVersion 21
|
||||||
buildToolsVersion "20.0.0"
|
buildToolsVersion '21.0.2'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId 'com.faizmalkani.floatingactionbutton'
|
applicationId 'com.faizmalkani.floatingactionbutton'
|
||||||
minSdkVersion 14
|
minSdkVersion 7
|
||||||
targetSdkVersion 19
|
targetSdkVersion 21
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
versionCode 1
|
versionCode 1
|
||||||
}
|
}
|
||||||
@ -22,7 +22,12 @@ android {
|
|||||||
assets.srcDirs = ['assets']
|
assets.srcDirs = ['assets']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_7
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_7
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
compile 'com.nineoldandroids:library:2.4.0'
|
||||||
}
|
}
|
@ -5,9 +5,14 @@ package com.faizmalkani.floatingactionbutton;
|
|||||||
|
|
||||||
public final class BuildConfig {
|
public final class BuildConfig {
|
||||||
public static final boolean DEBUG = Boolean.parseBoolean("true");
|
public static final boolean DEBUG = Boolean.parseBoolean("true");
|
||||||
public static final String PACKAGE_NAME = "com.faizmalkani.floatingactionbutton";
|
public static final String APPLICATION_ID = "com.faizmalkani.floatingactionbutton";
|
||||||
public static final String BUILD_TYPE = "debug";
|
public static final String BUILD_TYPE = "debug";
|
||||||
public static final String FLAVOR = "";
|
public static final String FLAVOR = "";
|
||||||
public static final int VERSION_CODE = 1;
|
public static final int VERSION_CODE = 1;
|
||||||
public static final String VERSION_NAME = "1.0";
|
public static final String VERSION_NAME = "1.0";
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #APPLICATION_ID}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public static final String PACKAGE_NAME = "com.faizmalkani.floatingactionbutton";
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,14 @@ package com.faizmalkani.floatingactionbutton;
|
|||||||
|
|
||||||
public final class BuildConfig {
|
public final class BuildConfig {
|
||||||
public static final boolean DEBUG = false;
|
public static final boolean DEBUG = false;
|
||||||
public static final String PACKAGE_NAME = "com.faizmalkani.floatingactionbutton";
|
public static final String APPLICATION_ID = "com.faizmalkani.floatingactionbutton";
|
||||||
public static final String BUILD_TYPE = "release";
|
public static final String BUILD_TYPE = "release";
|
||||||
public static final String FLAVOR = "";
|
public static final String FLAVOR = "";
|
||||||
public static final int VERSION_CODE = 1;
|
public static final int VERSION_CODE = 1;
|
||||||
public static final String VERSION_NAME = "1.0";
|
public static final String VERSION_NAME = "1.0";
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #APPLICATION_ID}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public static final String PACKAGE_NAME = "com.faizmalkani.floatingactionbutton";
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,14 @@ package com.faizmalkani.floatingactionbutton.test;
|
|||||||
|
|
||||||
public final class BuildConfig {
|
public final class BuildConfig {
|
||||||
public static final boolean DEBUG = Boolean.parseBoolean("true");
|
public static final boolean DEBUG = Boolean.parseBoolean("true");
|
||||||
public static final String PACKAGE_NAME = "com.faizmalkani.floatingactionbutton.test";
|
public static final String APPLICATION_ID = "com.faizmalkani.floatingactionbutton.test";
|
||||||
public static final String BUILD_TYPE = "debug";
|
public static final String BUILD_TYPE = "debug";
|
||||||
public static final String FLAVOR = "";
|
public static final String FLAVOR = "";
|
||||||
public static final int VERSION_CODE = 1;
|
public static final int VERSION_CODE = 1;
|
||||||
public static final String VERSION_NAME = "1.0";
|
public static final String VERSION_NAME = "1.0";
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #APPLICATION_ID}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public static final String PACKAGE_NAME = "com.faizmalkani.floatingactionbutton.test";
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ theme attribute (in the form
|
|||||||
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
*/
|
*/
|
||||||
public static int color=0x7f010001;
|
public static int colour=0x7f010001;
|
||||||
/** <p>Must be an integer value, such as "<code>100</code>".
|
/** <p>Must be an integer value, such as "<code>100</code>".
|
||||||
<p>This may also be a reference to a resource (in the form
|
<p>This may also be a reference to a resource (in the form
|
||||||
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
|
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
|
||||||
@ -66,14 +66,14 @@ containing a value of this type.
|
|||||||
<colgroup align="left" />
|
<colgroup align="left" />
|
||||||
<colgroup align="left" />
|
<colgroup align="left" />
|
||||||
<tr><th>Attribute</th><th>Description</th></tr>
|
<tr><th>Attribute</th><th>Description</th></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_color com.faizmalkani.floatingactionbutton:color}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_colour com.faizmalkani.floatingactionbutton:colour}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_drawable com.faizmalkani.floatingactionbutton:drawable}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_drawable com.faizmalkani.floatingactionbutton:drawable}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_shadowColor com.faizmalkani.floatingactionbutton:shadowColor}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_shadowColor com.faizmalkani.floatingactionbutton:shadowColor}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_shadowDx com.faizmalkani.floatingactionbutton:shadowDx}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_shadowDx com.faizmalkani.floatingactionbutton:shadowDx}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_shadowDy com.faizmalkani.floatingactionbutton:shadowDy}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_shadowDy com.faizmalkani.floatingactionbutton:shadowDy}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_shadowRadius com.faizmalkani.floatingactionbutton:shadowRadius}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_shadowRadius com.faizmalkani.floatingactionbutton:shadowRadius}</code></td><td></td></tr>
|
||||||
</table>
|
</table>
|
||||||
@see #FloatingActionButton_color
|
@see #FloatingActionButton_colour
|
||||||
@see #FloatingActionButton_drawable
|
@see #FloatingActionButton_drawable
|
||||||
@see #FloatingActionButton_shadowColor
|
@see #FloatingActionButton_shadowColor
|
||||||
@see #FloatingActionButton_shadowDx
|
@see #FloatingActionButton_shadowDx
|
||||||
@ -85,7 +85,7 @@ containing a value of this type.
|
|||||||
0x7f010004, 0x7f010005
|
0x7f010004, 0x7f010005
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#color}
|
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#colour}
|
||||||
attribute's value can be found in the {@link #FloatingActionButton} array.
|
attribute's value can be found in the {@link #FloatingActionButton} array.
|
||||||
|
|
||||||
|
|
||||||
@ -96,9 +96,9 @@ containing a value of this type.
|
|||||||
theme attribute (in the form
|
theme attribute (in the form
|
||||||
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
@attr name com.faizmalkani.floatingactionbutton:color
|
@attr name com.faizmalkani.floatingactionbutton:colour
|
||||||
*/
|
*/
|
||||||
public static final int FloatingActionButton_color = 1;
|
public static int FloatingActionButton_colour = 1;
|
||||||
/**
|
/**
|
||||||
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#drawable}
|
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#drawable}
|
||||||
attribute's value can be found in the {@link #FloatingActionButton} array.
|
attribute's value can be found in the {@link #FloatingActionButton} array.
|
||||||
@ -112,7 +112,7 @@ theme attribute (in the form
|
|||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
@attr name com.faizmalkani.floatingactionbutton:drawable
|
@attr name com.faizmalkani.floatingactionbutton:drawable
|
||||||
*/
|
*/
|
||||||
public static final int FloatingActionButton_drawable = 0;
|
public static int FloatingActionButton_drawable = 0;
|
||||||
/**
|
/**
|
||||||
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowColor}
|
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowColor}
|
||||||
attribute's value can be found in the {@link #FloatingActionButton} array.
|
attribute's value can be found in the {@link #FloatingActionButton} array.
|
||||||
@ -126,7 +126,7 @@ theme attribute (in the form
|
|||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
@attr name com.faizmalkani.floatingactionbutton:shadowColor
|
@attr name com.faizmalkani.floatingactionbutton:shadowColor
|
||||||
*/
|
*/
|
||||||
public static final int FloatingActionButton_shadowColor = 5;
|
public static int FloatingActionButton_shadowColor = 5;
|
||||||
/**
|
/**
|
||||||
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDx}
|
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDx}
|
||||||
attribute's value can be found in the {@link #FloatingActionButton} array.
|
attribute's value can be found in the {@link #FloatingActionButton} array.
|
||||||
@ -140,7 +140,7 @@ theme attribute (in the form
|
|||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
@attr name com.faizmalkani.floatingactionbutton:shadowDx
|
@attr name com.faizmalkani.floatingactionbutton:shadowDx
|
||||||
*/
|
*/
|
||||||
public static final int FloatingActionButton_shadowDx = 3;
|
public static int FloatingActionButton_shadowDx = 3;
|
||||||
/**
|
/**
|
||||||
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDy}
|
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDy}
|
||||||
attribute's value can be found in the {@link #FloatingActionButton} array.
|
attribute's value can be found in the {@link #FloatingActionButton} array.
|
||||||
@ -154,7 +154,7 @@ theme attribute (in the form
|
|||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
@attr name com.faizmalkani.floatingactionbutton:shadowDy
|
@attr name com.faizmalkani.floatingactionbutton:shadowDy
|
||||||
*/
|
*/
|
||||||
public static final int FloatingActionButton_shadowDy = 4;
|
public static int FloatingActionButton_shadowDy = 4;
|
||||||
/**
|
/**
|
||||||
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowRadius}
|
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowRadius}
|
||||||
attribute's value can be found in the {@link #FloatingActionButton} array.
|
attribute's value can be found in the {@link #FloatingActionButton} array.
|
||||||
@ -168,6 +168,6 @@ theme attribute (in the form
|
|||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
@attr name com.faizmalkani.floatingactionbutton:shadowRadius
|
@attr name com.faizmalkani.floatingactionbutton:shadowRadius
|
||||||
*/
|
*/
|
||||||
public static final int FloatingActionButton_shadowRadius = 2;
|
public static int FloatingActionButton_shadowRadius = 2;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ theme attribute (in the form
|
|||||||
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
*/
|
*/
|
||||||
public static int color=0x7f010001;
|
public static int colour=0x7f010001;
|
||||||
/** <p>Must be an integer value, such as "<code>100</code>".
|
/** <p>Must be an integer value, such as "<code>100</code>".
|
||||||
<p>This may also be a reference to a resource (in the form
|
<p>This may also be a reference to a resource (in the form
|
||||||
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
|
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
|
||||||
@ -66,14 +66,14 @@ containing a value of this type.
|
|||||||
<colgroup align="left" />
|
<colgroup align="left" />
|
||||||
<colgroup align="left" />
|
<colgroup align="left" />
|
||||||
<tr><th>Attribute</th><th>Description</th></tr>
|
<tr><th>Attribute</th><th>Description</th></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_color com.faizmalkani.floatingactionbutton:color}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_colour com.faizmalkani.floatingactionbutton:colour}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_drawable com.faizmalkani.floatingactionbutton:drawable}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_drawable com.faizmalkani.floatingactionbutton:drawable}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_shadowColor com.faizmalkani.floatingactionbutton:shadowColor}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_shadowColor com.faizmalkani.floatingactionbutton:shadowColor}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_shadowDx com.faizmalkani.floatingactionbutton:shadowDx}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_shadowDx com.faizmalkani.floatingactionbutton:shadowDx}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_shadowDy com.faizmalkani.floatingactionbutton:shadowDy}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_shadowDy com.faizmalkani.floatingactionbutton:shadowDy}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_shadowRadius com.faizmalkani.floatingactionbutton:shadowRadius}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_shadowRadius com.faizmalkani.floatingactionbutton:shadowRadius}</code></td><td></td></tr>
|
||||||
</table>
|
</table>
|
||||||
@see #FloatingActionButton_color
|
@see #FloatingActionButton_colour
|
||||||
@see #FloatingActionButton_drawable
|
@see #FloatingActionButton_drawable
|
||||||
@see #FloatingActionButton_shadowColor
|
@see #FloatingActionButton_shadowColor
|
||||||
@see #FloatingActionButton_shadowDx
|
@see #FloatingActionButton_shadowDx
|
||||||
@ -85,7 +85,7 @@ containing a value of this type.
|
|||||||
0x7f010004, 0x7f010005
|
0x7f010004, 0x7f010005
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#color}
|
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#colour}
|
||||||
attribute's value can be found in the {@link #FloatingActionButton} array.
|
attribute's value can be found in the {@link #FloatingActionButton} array.
|
||||||
|
|
||||||
|
|
||||||
@ -96,9 +96,9 @@ containing a value of this type.
|
|||||||
theme attribute (in the form
|
theme attribute (in the form
|
||||||
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
@attr name com.faizmalkani.floatingactionbutton:color
|
@attr name com.faizmalkani.floatingactionbutton:colour
|
||||||
*/
|
*/
|
||||||
public static final int FloatingActionButton_color = 1;
|
public static int FloatingActionButton_colour = 1;
|
||||||
/**
|
/**
|
||||||
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#drawable}
|
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#drawable}
|
||||||
attribute's value can be found in the {@link #FloatingActionButton} array.
|
attribute's value can be found in the {@link #FloatingActionButton} array.
|
||||||
@ -112,7 +112,7 @@ theme attribute (in the form
|
|||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
@attr name com.faizmalkani.floatingactionbutton:drawable
|
@attr name com.faizmalkani.floatingactionbutton:drawable
|
||||||
*/
|
*/
|
||||||
public static final int FloatingActionButton_drawable = 0;
|
public static int FloatingActionButton_drawable = 0;
|
||||||
/**
|
/**
|
||||||
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowColor}
|
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowColor}
|
||||||
attribute's value can be found in the {@link #FloatingActionButton} array.
|
attribute's value can be found in the {@link #FloatingActionButton} array.
|
||||||
@ -126,7 +126,7 @@ theme attribute (in the form
|
|||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
@attr name com.faizmalkani.floatingactionbutton:shadowColor
|
@attr name com.faizmalkani.floatingactionbutton:shadowColor
|
||||||
*/
|
*/
|
||||||
public static final int FloatingActionButton_shadowColor = 5;
|
public static int FloatingActionButton_shadowColor = 5;
|
||||||
/**
|
/**
|
||||||
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDx}
|
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDx}
|
||||||
attribute's value can be found in the {@link #FloatingActionButton} array.
|
attribute's value can be found in the {@link #FloatingActionButton} array.
|
||||||
@ -140,7 +140,7 @@ theme attribute (in the form
|
|||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
@attr name com.faizmalkani.floatingactionbutton:shadowDx
|
@attr name com.faizmalkani.floatingactionbutton:shadowDx
|
||||||
*/
|
*/
|
||||||
public static final int FloatingActionButton_shadowDx = 3;
|
public static int FloatingActionButton_shadowDx = 3;
|
||||||
/**
|
/**
|
||||||
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDy}
|
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowDy}
|
||||||
attribute's value can be found in the {@link #FloatingActionButton} array.
|
attribute's value can be found in the {@link #FloatingActionButton} array.
|
||||||
@ -154,7 +154,7 @@ theme attribute (in the form
|
|||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
@attr name com.faizmalkani.floatingactionbutton:shadowDy
|
@attr name com.faizmalkani.floatingactionbutton:shadowDy
|
||||||
*/
|
*/
|
||||||
public static final int FloatingActionButton_shadowDy = 4;
|
public static int FloatingActionButton_shadowDy = 4;
|
||||||
/**
|
/**
|
||||||
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowRadius}
|
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.R.attr#shadowRadius}
|
||||||
attribute's value can be found in the {@link #FloatingActionButton} array.
|
attribute's value can be found in the {@link #FloatingActionButton} array.
|
||||||
@ -168,6 +168,6 @@ theme attribute (in the form
|
|||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
@attr name com.faizmalkani.floatingactionbutton:shadowRadius
|
@attr name com.faizmalkani.floatingactionbutton:shadowRadius
|
||||||
*/
|
*/
|
||||||
public static final int FloatingActionButton_shadowRadius = 2;
|
public static int FloatingActionButton_shadowRadius = 2;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ package com.faizmalkani.floatingactionbutton;
|
|||||||
|
|
||||||
public final class R {
|
public final class R {
|
||||||
public static final class attr {
|
public static final class attr {
|
||||||
public static final int color = 0x7f010001;
|
public static final int colour = 0x7f010001;
|
||||||
public static final int drawable = 0x7f010000;
|
public static final int drawable = 0x7f010000;
|
||||||
public static final int shadowColor = 0x7f010005;
|
public static final int shadowColor = 0x7f010005;
|
||||||
public static final int shadowDx = 0x7f010003;
|
public static final int shadowDx = 0x7f010003;
|
||||||
@ -17,7 +17,7 @@ public final class R {
|
|||||||
}
|
}
|
||||||
public static final class styleable {
|
public static final class styleable {
|
||||||
public static final int[] FloatingActionButton = { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 };
|
public static final int[] FloatingActionButton = { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 };
|
||||||
public static final int FloatingActionButton_color = 1;
|
public static final int FloatingActionButton_colour = 1;
|
||||||
public static final int FloatingActionButton_drawable = 0;
|
public static final int FloatingActionButton_drawable = 0;
|
||||||
public static final int FloatingActionButton_shadowColor = 5;
|
public static final int FloatingActionButton_shadowColor = 5;
|
||||||
public static final int FloatingActionButton_shadowDx = 3;
|
public static final int FloatingActionButton_shadowDx = 3;
|
||||||
|
@ -17,7 +17,7 @@ theme attribute (in the form
|
|||||||
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
*/
|
*/
|
||||||
public static final int color=0x7f010001;
|
public static final int colour=0x7f010001;
|
||||||
/** <p>Must be an integer value, such as "<code>100</code>".
|
/** <p>Must be an integer value, such as "<code>100</code>".
|
||||||
<p>This may also be a reference to a resource (in the form
|
<p>This may also be a reference to a resource (in the form
|
||||||
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
|
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
|
||||||
@ -66,14 +66,14 @@ containing a value of this type.
|
|||||||
<colgroup align="left" />
|
<colgroup align="left" />
|
||||||
<colgroup align="left" />
|
<colgroup align="left" />
|
||||||
<tr><th>Attribute</th><th>Description</th></tr>
|
<tr><th>Attribute</th><th>Description</th></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_color com.faizmalkani.floatingactionbutton.test:color}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_colour com.faizmalkani.floatingactionbutton.test:colour}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_drawable com.faizmalkani.floatingactionbutton.test:drawable}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_drawable com.faizmalkani.floatingactionbutton.test:drawable}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_shadowColor com.faizmalkani.floatingactionbutton.test:shadowColor}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_shadowColor com.faizmalkani.floatingactionbutton.test:shadowColor}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_shadowDx com.faizmalkani.floatingactionbutton.test:shadowDx}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_shadowDx com.faizmalkani.floatingactionbutton.test:shadowDx}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_shadowDy com.faizmalkani.floatingactionbutton.test:shadowDy}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_shadowDy com.faizmalkani.floatingactionbutton.test:shadowDy}</code></td><td></td></tr>
|
||||||
<tr><td><code>{@link #FloatingActionButton_shadowRadius com.faizmalkani.floatingactionbutton.test:shadowRadius}</code></td><td></td></tr>
|
<tr><td><code>{@link #FloatingActionButton_shadowRadius com.faizmalkani.floatingactionbutton.test:shadowRadius}</code></td><td></td></tr>
|
||||||
</table>
|
</table>
|
||||||
@see #FloatingActionButton_color
|
@see #FloatingActionButton_colour
|
||||||
@see #FloatingActionButton_drawable
|
@see #FloatingActionButton_drawable
|
||||||
@see #FloatingActionButton_shadowColor
|
@see #FloatingActionButton_shadowColor
|
||||||
@see #FloatingActionButton_shadowDx
|
@see #FloatingActionButton_shadowDx
|
||||||
@ -85,7 +85,7 @@ containing a value of this type.
|
|||||||
0x7f010004, 0x7f010005
|
0x7f010004, 0x7f010005
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#color}
|
<p>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.
|
attribute's value can be found in the {@link #FloatingActionButton} array.
|
||||||
|
|
||||||
|
|
||||||
@ -96,9 +96,9 @@ containing a value of this type.
|
|||||||
theme attribute (in the form
|
theme attribute (in the form
|
||||||
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
||||||
containing a value of this type.
|
containing a value of this type.
|
||||||
@attr name com.faizmalkani.floatingactionbutton.test:color
|
@attr name com.faizmalkani.floatingactionbutton.test:colour
|
||||||
*/
|
*/
|
||||||
public static final int FloatingActionButton_color = 1;
|
public static final int FloatingActionButton_colour = 1;
|
||||||
/**
|
/**
|
||||||
<p>This symbol is the offset where the {@link com.faizmalkani.floatingactionbutton.test.R.attr#drawable}
|
<p>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.
|
attribute's value can be found in the {@link #FloatingActionButton} array.
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
android:versionName="1.0" >
|
android:versionName="1.0" >
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="14"
|
android:minSdkVersion="7"
|
||||||
android:targetSdkVersion="19" />
|
android:targetSdkVersion="21" />
|
||||||
|
|
||||||
<application android:allowBackup="true" >
|
<application android:allowBackup="true" >
|
||||||
</application>
|
</application>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
int attr color 0x7f010001
|
int attr colour 0x7f010001
|
||||||
int attr drawable 0x7f010000
|
int attr drawable 0x7f010000
|
||||||
int attr shadowColor 0x7f010005
|
int attr shadowColor 0x7f010005
|
||||||
int attr shadowDx 0x7f010003
|
int attr shadowDx 0x7f010003
|
||||||
int attr shadowDy 0x7f010004
|
int attr shadowDy 0x7f010004
|
||||||
int attr shadowRadius 0x7f010002
|
int attr shadowRadius 0x7f010002
|
||||||
int[] styleable FloatingActionButton { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 }
|
int[] styleable FloatingActionButton { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 }
|
||||||
int styleable FloatingActionButton_color 1
|
int styleable FloatingActionButton_colour 1
|
||||||
int styleable FloatingActionButton_drawable 0
|
int styleable FloatingActionButton_drawable 0
|
||||||
int styleable FloatingActionButton_shadowColor 5
|
int styleable FloatingActionButton_shadowColor 5
|
||||||
int styleable FloatingActionButton_shadowDx 3
|
int styleable FloatingActionButton_shadowDx 3
|
||||||
|
Binary file not shown.
@ -1,16 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<declare-styleable name="FloatingActionButton"><attr format="integer" name="drawable"/><attr format="color" name="colour"/><attr format="float" name="shadowRadius"/><attr format="float" name="shadowDx"/><attr format="float" name="shadowDy"/><attr format="integer" name="shadowColor"/></declare-styleable>
|
||||||
<!-- From: file:/C:/Users/Vlad/Documents/AndroidStudioProjects/turbo-editor/libraries/FloatingActionButton/res/values/attrs.xml -->
|
</resources>
|
||||||
<eat-comment />
|
|
||||||
|
|
||||||
<declare-styleable name="FloatingActionButton">
|
|
||||||
<attr name="drawable" format="integer" />
|
|
||||||
<attr name="color" format="color" />
|
|
||||||
<attr name="shadowRadius" format="float" />
|
|
||||||
<attr name="shadowDx" format="float" />
|
|
||||||
<attr name="shadowDy" format="float" />
|
|
||||||
<attr name="shadowColor" format="integer" />
|
|
||||||
</declare-styleable>
|
|
||||||
|
|
||||||
</resources>
|
|
@ -5,8 +5,8 @@
|
|||||||
android:versionName="1.0" >
|
android:versionName="1.0" >
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="14"
|
android:minSdkVersion="7"
|
||||||
android:targetSdkVersion="19" />
|
android:targetSdkVersion="21" />
|
||||||
|
|
||||||
<application android:allowBackup="true" >
|
<application android:allowBackup="true" >
|
||||||
</application>
|
</application>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
int attr color 0x7f010001
|
int attr colour 0x7f010001
|
||||||
int attr drawable 0x7f010000
|
int attr drawable 0x7f010000
|
||||||
int attr shadowColor 0x7f010005
|
int attr shadowColor 0x7f010005
|
||||||
int attr shadowDx 0x7f010003
|
int attr shadowDx 0x7f010003
|
||||||
int attr shadowDy 0x7f010004
|
int attr shadowDy 0x7f010004
|
||||||
int attr shadowRadius 0x7f010002
|
int attr shadowRadius 0x7f010002
|
||||||
int[] styleable FloatingActionButton { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 }
|
int[] styleable FloatingActionButton { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 }
|
||||||
int styleable FloatingActionButton_color 1
|
int styleable FloatingActionButton_colour 1
|
||||||
int styleable FloatingActionButton_drawable 0
|
int styleable FloatingActionButton_drawable 0
|
||||||
int styleable FloatingActionButton_shadowColor 5
|
int styleable FloatingActionButton_shadowColor 5
|
||||||
int styleable FloatingActionButton_shadowDx 3
|
int styleable FloatingActionButton_shadowDx 3
|
||||||
|
Binary file not shown.
@ -1,16 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<declare-styleable name="FloatingActionButton"><attr format="integer" name="drawable"/><attr format="color" name="colour"/><attr format="float" name="shadowRadius"/><attr format="float" name="shadowDx"/><attr format="float" name="shadowDy"/><attr format="integer" name="shadowColor"/></declare-styleable>
|
||||||
<!-- From: file:/C:/Users/Vlad/Documents/AndroidStudioProjects/turbo-editor/libraries/FloatingActionButton/res/values/attrs.xml -->
|
</resources>
|
||||||
<eat-comment />
|
|
||||||
|
|
||||||
<declare-styleable name="FloatingActionButton">
|
|
||||||
<attr name="drawable" format="integer" />
|
|
||||||
<attr name="color" format="color" />
|
|
||||||
<attr name="shadowRadius" format="float" />
|
|
||||||
<attr name="shadowDx" format="float" />
|
|
||||||
<attr name="shadowDy" format="float" />
|
|
||||||
<attr name="shadowColor" format="integer" />
|
|
||||||
</declare-styleable>
|
|
||||||
|
|
||||||
</resources>
|
|
@ -1,11 +1,2 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<merger version="2" >
|
<merger version="3"><dataSet config="main"><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\assets"/></dataSet><dataSet config="debug"><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\src\debug\assets"/></dataSet></merger>
|
||||||
|
|
||||||
<dataSet config="main" >
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\assets" />
|
|
||||||
</dataSet>
|
|
||||||
<dataSet config="debug" >
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\src\debug\assets" />
|
|
||||||
</dataSet>
|
|
||||||
|
|
||||||
</merger>
|
|
@ -1,11 +1,2 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<merger version="2" >
|
<merger version="3"><dataSet config="main"><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\assets"/></dataSet><dataSet config="release"><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\src\release\assets"/></dataSet></merger>
|
||||||
|
|
||||||
<dataSet config="main" >
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\assets" />
|
|
||||||
</dataSet>
|
|
||||||
<dataSet config="release" >
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\src\release\assets" />
|
|
||||||
</dataSet>
|
|
||||||
|
|
||||||
</merger>
|
|
@ -1,11 +1,2 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<merger version="2" >
|
<merger version="3"><dataSet config="debug"><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\intermediates\bundles\debug\assets"/></dataSet><dataSet config="main"><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\src\androidTest\assets"/></dataSet></merger>
|
||||||
|
|
||||||
<dataSet config="debug" >
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\intermediates\bundles\debug\assets" />
|
|
||||||
</dataSet>
|
|
||||||
<dataSet config="main" >
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\src\androidTest\assets" />
|
|
||||||
</dataSet>
|
|
||||||
|
|
||||||
</merger>
|
|
@ -1,38 +1,2 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<merger version="2" >
|
<merger version="3"><dataSet config="debug"><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\intermediates\bundles\debug\res"><file path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\intermediates\bundles\debug\res\values\values.xml" qualifiers=""><declare-styleable name="FloatingActionButton"><attr format="integer" name="drawable"/><attr format="color" name="colour"/><attr format="float" name="shadowRadius"/><attr format="float" name="shadowDx"/><attr format="float" name="shadowDy"/><attr format="integer" name="shadowColor"/></declare-styleable></file></source></dataSet><dataSet config="main"><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\src\androidTest\res"/><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\generated\res\rs\test\debug"/><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\generated\res\generated\test\debug"/></dataSet><mergedItems><configuration qualifiers=""><declare-styleable name="FloatingActionButton"><attr format="integer" name="drawable"/><attr format="color" name="colour"/><attr format="float" name="shadowRadius"/><attr format="float" name="shadowDx"/><attr format="float" name="shadowDy"/><attr format="integer" name="shadowColor"/></declare-styleable></configuration></mergedItems></merger>
|
||||||
|
|
||||||
<dataSet config="debug" >
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\intermediates\bundles\debug\res" >
|
|
||||||
<file
|
|
||||||
path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\intermediates\bundles\debug\res\values\values.xml"
|
|
||||||
qualifiers="" >
|
|
||||||
<declare-styleable name="FloatingActionButton" >
|
|
||||||
<attr
|
|
||||||
name="drawable"
|
|
||||||
format="integer" />
|
|
||||||
<attr
|
|
||||||
name="color"
|
|
||||||
format="color" />
|
|
||||||
<attr
|
|
||||||
name="shadowRadius"
|
|
||||||
format="float" />
|
|
||||||
<attr
|
|
||||||
name="shadowDx"
|
|
||||||
format="float" />
|
|
||||||
<attr
|
|
||||||
name="shadowDy"
|
|
||||||
format="float" />
|
|
||||||
<attr
|
|
||||||
name="shadowColor"
|
|
||||||
format="integer" />
|
|
||||||
</declare-styleable>
|
|
||||||
</file>
|
|
||||||
</source>
|
|
||||||
</dataSet>
|
|
||||||
<dataSet config="main" >
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\src\androidTest\res" />
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\generated\res\rs\test\debug" />
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\generated\res\generated\test\debug" />
|
|
||||||
</dataSet>
|
|
||||||
|
|
||||||
</merger>
|
|
@ -1,38 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<merger version="2" >
|
<merger version="3"><dataSet config="main"><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\res"><file path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\res\values\attrs.xml" qualifiers=""><declare-styleable name="FloatingActionButton">
|
||||||
|
<attr format="integer" name="drawable"/>
|
||||||
<dataSet config="main" >
|
<attr format="color" name="colour"/>
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\res" >
|
<attr format="float" name="shadowRadius"/>
|
||||||
<file
|
<attr format="float" name="shadowDx"/>
|
||||||
path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\res\values\attrs.xml"
|
<attr format="float" name="shadowDy"/>
|
||||||
qualifiers="" >
|
<attr format="integer" name="shadowColor"/>
|
||||||
<declare-styleable name="FloatingActionButton" >
|
</declare-styleable></file></source><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\generated\res\rs\debug"/><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\generated\res\generated\debug"/></dataSet><dataSet config="debug"><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\src\debug\res"/></dataSet><mergedItems><configuration qualifiers=""><declare-styleable name="FloatingActionButton"><attr format="integer" name="drawable"/><attr format="color" name="colour"/><attr format="float" name="shadowRadius"/><attr format="float" name="shadowDx"/><attr format="float" name="shadowDy"/><attr format="integer" name="shadowColor"/></declare-styleable></configuration></mergedItems></merger>
|
||||||
<attr
|
|
||||||
name="drawable"
|
|
||||||
format="integer" />
|
|
||||||
<attr
|
|
||||||
name="color"
|
|
||||||
format="color" />
|
|
||||||
<attr
|
|
||||||
name="shadowRadius"
|
|
||||||
format="float" />
|
|
||||||
<attr
|
|
||||||
name="shadowDx"
|
|
||||||
format="float" />
|
|
||||||
<attr
|
|
||||||
name="shadowDy"
|
|
||||||
format="float" />
|
|
||||||
<attr
|
|
||||||
name="shadowColor"
|
|
||||||
format="integer" />
|
|
||||||
</declare-styleable>
|
|
||||||
</file>
|
|
||||||
</source>
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\generated\res\rs\debug" />
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\generated\res\generated\debug" />
|
|
||||||
</dataSet>
|
|
||||||
<dataSet config="debug" >
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\src\debug\res" />
|
|
||||||
</dataSet>
|
|
||||||
|
|
||||||
</merger>
|
|
@ -1,38 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<merger version="2" >
|
<merger version="3"><dataSet config="main"><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\res"><file path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\res\values\attrs.xml" qualifiers=""><declare-styleable name="FloatingActionButton">
|
||||||
|
<attr format="integer" name="drawable"/>
|
||||||
<dataSet config="main" >
|
<attr format="color" name="colour"/>
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\res" >
|
<attr format="float" name="shadowRadius"/>
|
||||||
<file
|
<attr format="float" name="shadowDx"/>
|
||||||
path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\res\values\attrs.xml"
|
<attr format="float" name="shadowDy"/>
|
||||||
qualifiers="" >
|
<attr format="integer" name="shadowColor"/>
|
||||||
<declare-styleable name="FloatingActionButton" >
|
</declare-styleable></file></source><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\generated\res\rs\release"/><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\generated\res\generated\release"/></dataSet><dataSet config="release"><source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\src\release\res"/></dataSet><mergedItems><configuration qualifiers=""><declare-styleable name="FloatingActionButton"><attr format="integer" name="drawable"/><attr format="color" name="colour"/><attr format="float" name="shadowRadius"/><attr format="float" name="shadowDx"/><attr format="float" name="shadowDy"/><attr format="integer" name="shadowColor"/></declare-styleable></configuration></mergedItems></merger>
|
||||||
<attr
|
|
||||||
name="drawable"
|
|
||||||
format="integer" />
|
|
||||||
<attr
|
|
||||||
name="color"
|
|
||||||
format="color" />
|
|
||||||
<attr
|
|
||||||
name="shadowRadius"
|
|
||||||
format="float" />
|
|
||||||
<attr
|
|
||||||
name="shadowDx"
|
|
||||||
format="float" />
|
|
||||||
<attr
|
|
||||||
name="shadowDy"
|
|
||||||
format="float" />
|
|
||||||
<attr
|
|
||||||
name="shadowColor"
|
|
||||||
format="integer" />
|
|
||||||
</declare-styleable>
|
|
||||||
</file>
|
|
||||||
</source>
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\generated\res\rs\release" />
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\build\generated\res\generated\release" />
|
|
||||||
</dataSet>
|
|
||||||
<dataSet config="release" >
|
|
||||||
<source path="C:\Users\Vlad\Documents\AndroidStudioProjects\turbo-editor\libraries\FloatingActionButton\src\release\res" />
|
|
||||||
</dataSet>
|
|
||||||
|
|
||||||
</merger>
|
|
@ -3,8 +3,8 @@
|
|||||||
package="com.faizmalkani.floatingactionbutton.test" >
|
package="com.faizmalkani.floatingactionbutton.test" >
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="14"
|
android:minSdkVersion="7"
|
||||||
android:targetSdkVersion="19" />
|
android:targetSdkVersion="21" />
|
||||||
|
|
||||||
<instrumentation
|
<instrumentation
|
||||||
android:name="android.test.InstrumentationTestRunner"
|
android:name="android.test.InstrumentationTestRunner"
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.faizmalkani.floatingactionbutton.test">
|
||||||
|
|
||||||
|
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="21" />
|
||||||
|
|
||||||
|
<application>
|
||||||
|
<uses-library android:name="android.test.runner" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<instrumentation android:name="android.test.InstrumentationTestRunner"
|
||||||
|
android:targetPackage="com.faizmalkani.floatingactionbutton.test"
|
||||||
|
android:handleProfiling="false"
|
||||||
|
android:functionalTest="false"
|
||||||
|
android:label="Tests for com.faizmalkani.floatingactionbutton.test"/>
|
||||||
|
</manifest>
|
@ -1,16 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<declare-styleable name="FloatingActionButton"><attr format="integer" name="drawable"/><attr format="color" name="colour"/><attr format="float" name="shadowRadius"/><attr format="float" name="shadowDx"/><attr format="float" name="shadowDy"/><attr format="integer" name="shadowColor"/></declare-styleable>
|
||||||
<!-- From: file:/C:/Users/Vlad/Documents/AndroidStudioProjects/turbo-editor/libraries/FloatingActionButton/build/intermediates/bundles/debug/res/values/values.xml -->
|
</resources>
|
||||||
<eat-comment />
|
|
||||||
|
|
||||||
<declare-styleable name="FloatingActionButton">
|
|
||||||
<attr name="drawable" format="integer" />
|
|
||||||
<attr name="color" format="color" />
|
|
||||||
<attr name="shadowRadius" format="float" />
|
|
||||||
<attr name="shadowDx" format="float" />
|
|
||||||
<attr name="shadowDy" format="float" />
|
|
||||||
<attr name="shadowColor" format="integer" />
|
|
||||||
</declare-styleable>
|
|
||||||
|
|
||||||
</resources>
|
|
@ -1,11 +1,11 @@
|
|||||||
int attr color 0x7f010001
|
int attr colour 0x7f010001
|
||||||
int attr drawable 0x7f010000
|
int attr drawable 0x7f010000
|
||||||
int attr shadowColor 0x7f010005
|
int attr shadowColor 0x7f010005
|
||||||
int attr shadowDx 0x7f010003
|
int attr shadowDx 0x7f010003
|
||||||
int attr shadowDy 0x7f010004
|
int attr shadowDy 0x7f010004
|
||||||
int attr shadowRadius 0x7f010002
|
int attr shadowRadius 0x7f010002
|
||||||
int[] styleable FloatingActionButton { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 }
|
int[] styleable FloatingActionButton { 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005 }
|
||||||
int styleable FloatingActionButton_color 1
|
int styleable FloatingActionButton_colour 1
|
||||||
int styleable FloatingActionButton_drawable 0
|
int styleable FloatingActionButton_drawable 0
|
||||||
int styleable FloatingActionButton_shadowColor 5
|
int styleable FloatingActionButton_shadowColor 5
|
||||||
int styleable FloatingActionButton_shadowDx 3
|
int styleable FloatingActionButton_shadowDx 3
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
# This file is automatically generated by Android Tools.
|
# This file is automatically generated by Android Tools.
|
||||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
#
|
#
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<declare-styleable name="FloatingActionButton">
|
<declare-styleable name="FloatingActionButton">
|
||||||
<attr name="drawable" format="integer"/>
|
<attr name="drawable" format="integer"/>
|
||||||
<attr name="color" format="color"/>
|
<attr name="colour" format="color"/>
|
||||||
<attr name="shadowRadius" format="float"/>
|
<attr name="shadowRadius" format="float"/>
|
||||||
<attr name="shadowDx" format="float"/>
|
<attr name="shadowDx" format="float"/>
|
||||||
<attr name="shadowDy" format="float"/>
|
<attr name="shadowDy" format="float"/>
|
||||||
|
@ -1,10 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014 SBG Apps
|
||||||
|
*
|
||||||
|
* 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 com.faizmalkani.floatingactionbutton;
|
package com.faizmalkani.floatingactionbutton;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AbsListView;
|
import android.widget.AbsListView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stéphane on 09/07/2014.
|
||||||
|
*/
|
||||||
class DirectionScrollListener implements AbsListView.OnScrollListener {
|
class DirectionScrollListener implements AbsListView.OnScrollListener {
|
||||||
|
|
||||||
private static final int DIRECTION_CHANGE_THRESHOLD = 1;
|
private static final int DIRECTION_CHANGE_THRESHOLD = 1;
|
||||||
@ -34,10 +51,7 @@ class DirectionScrollListener implements AbsListView.OnScrollListener {
|
|||||||
goingDown = firstVisibleItem > mPrevPosition;
|
goingDown = firstVisibleItem > mPrevPosition;
|
||||||
}
|
}
|
||||||
if (changed && mUpdated) {
|
if (changed && mUpdated) {
|
||||||
if(goingDown)
|
mFloatingActionButton.hide(goingDown);
|
||||||
mFloatingActionButton.hideFab();
|
|
||||||
else
|
|
||||||
mFloatingActionButton.showFab();
|
|
||||||
}
|
}
|
||||||
mPrevPosition = firstVisibleItem;
|
mPrevPosition = firstVisibleItem;
|
||||||
mPrevTop = firstViewTop;
|
mPrevTop = firstViewTop;
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
package com.faizmalkani.floatingactionbutton;
|
package com.faizmalkani.floatingactionbutton;
|
||||||
import android.animation.ObjectAnimator;
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
@ -11,135 +9,146 @@ import android.graphics.Paint;
|
|||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Build;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.DisplayMetrics;
|
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.animation.AccelerateInterpolator;
|
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||||
import android.view.animation.DecelerateInterpolator;
|
import android.view.animation.Interpolator;
|
||||||
import android.widget.AbsListView;
|
import android.widget.AbsListView;
|
||||||
|
|
||||||
public class FloatingActionButton extends View
|
import com.nineoldandroids.animation.ObjectAnimator;
|
||||||
{
|
import com.nineoldandroids.view.ViewHelper;
|
||||||
Context _context;
|
|
||||||
Paint mButtonPaint, mDrawablePaint;
|
|
||||||
Bitmap mBitmap;
|
|
||||||
int mScreenHeight;
|
|
||||||
float currentY;
|
|
||||||
boolean mHidden = false;
|
|
||||||
|
|
||||||
ObjectAnimator mShowAnimation;
|
public class FloatingActionButton extends View {
|
||||||
ObjectAnimator mHideAnimation;
|
|
||||||
|
|
||||||
public FloatingActionButton(Context context, AttributeSet attributeSet)
|
private final Interpolator mInterpolator = new AccelerateDecelerateInterpolator();
|
||||||
{
|
private final Paint mButtonPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
super(context, attributeSet);
|
private final Paint mDrawablePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
_context = context;
|
private Bitmap mBitmap;
|
||||||
init(Color.WHITE);
|
private int mColor;
|
||||||
|
private boolean mHidden = false;
|
||||||
|
/**
|
||||||
|
* The FAB button's Y position when it is displayed.
|
||||||
|
*/
|
||||||
|
private float mYDisplayed = -1;
|
||||||
|
/**
|
||||||
|
* The FAB button's Y position when it is hidden.
|
||||||
|
*/
|
||||||
|
private float mYHidden = -1;
|
||||||
|
|
||||||
|
public FloatingActionButton(Context context) {
|
||||||
|
this(context, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
public FloatingActionButton(Context context, AttributeSet attributeSet) {
|
||||||
public FloatingActionButton(Context context)
|
this(context, attributeSet, 0);
|
||||||
{
|
|
||||||
super(context);
|
|
||||||
_context = context;
|
|
||||||
init(Color.WHITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColor(int fabColor)
|
|
||||||
{
|
|
||||||
init(fabColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDrawable(Drawable fabDrawable)
|
|
||||||
{
|
|
||||||
mBitmap = ((BitmapDrawable) fabDrawable).getBitmap();
|
|
||||||
invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void init(int fabColor)
|
public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
{
|
super(context, attrs, defStyleAttr);
|
||||||
setWillNotDraw(false);
|
|
||||||
this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
|
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.FloatingActionButton);
|
||||||
mButtonPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
mColor = a.getColor(R.styleable.FloatingActionButton_colour, Color.WHITE);
|
||||||
mButtonPaint.setColor(fabColor);
|
|
||||||
mButtonPaint.setStyle(Paint.Style.FILL);
|
mButtonPaint.setStyle(Paint.Style.FILL);
|
||||||
mButtonPaint.setShadowLayer(10.0f, 0.0f, 3.5f, Color.argb(100, 0, 0, 0));
|
mButtonPaint.setColor(mColor);
|
||||||
mDrawablePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
float radius, dx, dy;
|
||||||
invalidate();
|
radius = a.getFloat(R.styleable.FloatingActionButton_shadowRadius, 10.0f);
|
||||||
|
dx = a.getFloat(R.styleable.FloatingActionButton_shadowDx, 0.0f);
|
||||||
|
dy = a.getFloat(R.styleable.FloatingActionButton_shadowDy, 3.5f);
|
||||||
|
int color = a.getInteger(R.styleable.FloatingActionButton_shadowColor, Color.argb(100, 0, 0, 0));
|
||||||
|
mButtonPaint.setShadowLayer(radius, dx, dy, color);
|
||||||
|
|
||||||
WindowManager mWindowManager = (WindowManager) _context.getSystemService(Context.WINDOW_SERVICE);
|
Drawable drawable = a.getDrawable(R.styleable.FloatingActionButton_drawable);
|
||||||
|
if (null != drawable) {
|
||||||
|
mBitmap = ((BitmapDrawable) drawable).getBitmap();
|
||||||
|
}
|
||||||
|
setWillNotDraw(false);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
|
||||||
|
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
|
||||||
|
|
||||||
|
WindowManager mWindowManager = (WindowManager)
|
||||||
|
context.getSystemService(Context.WINDOW_SERVICE);
|
||||||
Display display = mWindowManager.getDefaultDisplay();
|
Display display = mWindowManager.getDefaultDisplay();
|
||||||
Point size = new Point();
|
Point size = new Point();
|
||||||
display.getSize(size);
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
|
||||||
mScreenHeight = size.y;
|
display.getSize(size);
|
||||||
|
mYHidden = size.y;
|
||||||
|
} else mYHidden = display.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
mShowAnimation = ObjectAnimator.ofFloat(this, "Y", currentY);
|
public static int darkenColor(int color) {
|
||||||
mHideAnimation = ObjectAnimator.ofFloat(this, "Y", mScreenHeight);
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(color, hsv);
|
||||||
|
hsv[2] *= 0.8f;
|
||||||
|
return Color.HSVToColor(hsv);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(int color) {
|
||||||
|
mColor = color;
|
||||||
|
mButtonPaint.setColor(mColor);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDrawable(Drawable drawable) {
|
||||||
|
mBitmap = ((BitmapDrawable) drawable).getBitmap();
|
||||||
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas)
|
protected void onDraw(Canvas canvas) {
|
||||||
{
|
canvas.drawCircle(getWidth() / 2, getHeight() / 2, (float) (getWidth() / 2.6), mButtonPaint);
|
||||||
setClickable(true);
|
if (null != mBitmap) {
|
||||||
canvas.drawCircle(getWidth()/2, getHeight()/2,(float) (getWidth()/2.6), mButtonPaint);
|
canvas.drawBitmap(mBitmap, (getWidth() - mBitmap.getWidth()) / 2,
|
||||||
canvas.drawBitmap(mBitmap, (getWidth() - mBitmap.getWidth()) / 2, (getHeight() - mBitmap.getHeight()) / 2, mDrawablePaint);
|
(getHeight() - mBitmap.getHeight()) / 2, mDrawablePaint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent event)
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||||
{
|
// Perform the default behavior
|
||||||
if(event.getAction() == MotionEvent.ACTION_UP)
|
super.onLayout(changed, left, top, right, bottom);
|
||||||
{
|
|
||||||
setAlpha(1.0f);
|
// Store the FAB button's displayed Y position if we are not already aware of it
|
||||||
|
if (mYDisplayed == -1) {
|
||||||
|
|
||||||
|
mYDisplayed = ViewHelper.getY(this);
|
||||||
}
|
}
|
||||||
else if(event.getAction() == MotionEvent.ACTION_DOWN)
|
}
|
||||||
{
|
|
||||||
setAlpha(0.6f);
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
int color;
|
||||||
|
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||||
|
color = mColor;
|
||||||
|
} else {
|
||||||
|
color = darkenColor(mColor);
|
||||||
}
|
}
|
||||||
|
mButtonPaint.setColor(color);
|
||||||
|
invalidate();
|
||||||
return super.onTouchEvent(event);
|
return super.onTouchEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int dpToPx(int dp)
|
public void hide(boolean hide) {
|
||||||
{
|
// If the hidden state is being updated
|
||||||
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
|
if (mHidden != hide) {
|
||||||
return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void hideFab()
|
// Store the new hidden state
|
||||||
{
|
mHidden = hide;
|
||||||
if(!mHidden && mShowAnimation != null && !mShowAnimation.isRunning())
|
|
||||||
{
|
// Animate the FAB to it's new Y position
|
||||||
currentY = getY();
|
ObjectAnimator animator = ObjectAnimator.ofFloat(this, "y", mHidden ? mYHidden : mYDisplayed).setDuration(500);
|
||||||
mHideAnimation = ObjectAnimator.ofFloat(this, "Y", mScreenHeight);
|
animator.setInterpolator(mInterpolator);
|
||||||
mHideAnimation.setInterpolator(new AccelerateInterpolator());
|
animator.start();
|
||||||
mHideAnimation.start();
|
|
||||||
mHidden = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showFab()
|
|
||||||
{
|
|
||||||
if(mHidden && mHideAnimation != null && !mHideAnimation.isRunning())
|
|
||||||
{
|
|
||||||
mShowAnimation = ObjectAnimator.ofFloat(this, "Y", currentY);
|
|
||||||
mShowAnimation.setInterpolator(new DecelerateInterpolator());
|
|
||||||
mShowAnimation.start();
|
|
||||||
mHidden = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isHidden(){
|
|
||||||
return mHidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void listenTo(AbsListView listView) {
|
public void listenTo(AbsListView listView) {
|
||||||
if (null != listView) {
|
if (null != listView) {
|
||||||
listView.setOnScrollListener(new DirectionScrollListener(this));
|
listView.setOnScrollListener(new DirectionScrollListener(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -15,12 +15,16 @@ dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 20
|
compileSdkVersion 21
|
||||||
buildToolsVersion "20.0.0"
|
buildToolsVersion '21.0.2'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 7
|
minSdkVersion 7
|
||||||
targetSdkVersion 20
|
targetSdkVersion 21
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_7
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_7
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,13 +24,13 @@ android {
|
|||||||
disable 'MissingTranslation', 'ExtraTranslation'
|
disable 'MissingTranslation', 'ExtraTranslation'
|
||||||
}
|
}
|
||||||
|
|
||||||
compileSdkVersion 20
|
compileSdkVersion 21
|
||||||
buildToolsVersion "20.0.0"
|
buildToolsVersion '21.0.2'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "sharedcode.turboeditor"
|
applicationId "sharedcode.turboeditor"
|
||||||
minSdkVersion 14
|
minSdkVersion 11
|
||||||
targetSdkVersion 20
|
targetSdkVersion 21
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
}
|
}
|
||||||
@ -45,17 +45,32 @@ android {
|
|||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lintOptions {
|
||||||
|
abortOnError false
|
||||||
|
}
|
||||||
|
|
||||||
|
packagingOptions {
|
||||||
|
exclude 'META-INF/LICENSE.txt'
|
||||||
|
exclude 'META-INF/NOTICE.txt'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
compile project(':libraries:RootCommands')
|
compile project(':libraries:RootCommands')
|
||||||
compile project(':libraries:FloatingActionButton')
|
compile project(':libraries:FloatingActionButton')
|
||||||
compile "com.android.support:support-v4:19.0.+"
|
|
||||||
compile('de.greenrobot:eventbus:2.2.1') {
|
compile('de.greenrobot:eventbus:2.2.1') {
|
||||||
exclude module: 'support-v4'
|
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')
|
||||||
|
compile ("com.android.support:appcompat-v7:21.+") {
|
||||||
|
exclude group: 'com.android.support', module: 'support-v4'
|
||||||
|
}
|
||||||
|
compile 'com.android.support:support-v4:21.+'
|
||||||
compile 'com.github.gabrielemariotti.changeloglib:library:1.5.1'
|
compile 'com.github.gabrielemariotti.changeloglib:library:1.5.1'
|
||||||
compile 'commons-io:commons-io:2.4'
|
compile 'commons-io:commons-io:2.4'
|
||||||
|
compile 'com.android.support:support-annotations:20.0.0'
|
||||||
}
|
}
|
||||||
|
BIN
libraries/sharedCode/libs/juniversalchardet-1.0.3-sources.jar
Normal file
BIN
libraries/sharedCode/libs/juniversalchardet-1.0.3-sources.jar
Normal file
Binary file not shown.
@ -1,3 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
~ Copyright (C) 2014 Vlad Mihalachi
|
~ Copyright (C) 2014 Vlad Mihalachi
|
||||||
~
|
~
|
||||||
@ -15,10 +16,8 @@
|
|||||||
~
|
~
|
||||||
~ You should have received a copy of the GNU General Public License
|
~ You should have received a copy of the GNU General Public License
|
||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="sharedcode.turboeditor">
|
package="sharedcode.turboeditor" >
|
||||||
|
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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 com.android.vending.billing;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InAppBillingService is the service that provides in-app billing version 3 and beyond.
|
||||||
|
* This service provides the following features:
|
||||||
|
* 1. Provides a new API to get details of in-app items published for the app including
|
||||||
|
* price, type, title and description.
|
||||||
|
* 2. The purchase flow is synchronous and purchase information is available immediately
|
||||||
|
* after it completes.
|
||||||
|
* 3. Purchase information of in-app purchases is maintained within the Google Play system
|
||||||
|
* till the purchase is consumed.
|
||||||
|
* 4. An API to consume a purchase of an inapp item. All purchases of one-time
|
||||||
|
* in-app items are consumable and thereafter can be purchased again.
|
||||||
|
* 5. An API to get current purchases of the user immediately. This will not contain any
|
||||||
|
* consumed purchases.
|
||||||
|
*
|
||||||
|
* All calls will give a response code with the following possible values
|
||||||
|
* RESULT_OK = 0 - success
|
||||||
|
* RESULT_USER_CANCELED = 1 - user pressed back or canceled a dialog
|
||||||
|
* RESULT_BILLING_UNAVAILABLE = 3 - this billing API version is not supported for the type requested
|
||||||
|
* RESULT_ITEM_UNAVAILABLE = 4 - requested SKU is not available for purchase
|
||||||
|
* RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API
|
||||||
|
* RESULT_ERROR = 6 - Fatal error during the API action
|
||||||
|
* RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned
|
||||||
|
* RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned
|
||||||
|
*/
|
||||||
|
interface IInAppBillingService {
|
||||||
|
/**
|
||||||
|
* Checks support for the requested billing API version, package and in-app type.
|
||||||
|
* Minimum API version supported by this interface is 3.
|
||||||
|
* @param apiVersion the billing version which the app is using
|
||||||
|
* @param packageName the package name of the calling app
|
||||||
|
* @param type type of the in-app item being purchased "inapp" for one-time purchases
|
||||||
|
* and "subs" for subscription.
|
||||||
|
* @return RESULT_OK(0) on success, corresponding result code on failures
|
||||||
|
*/
|
||||||
|
int isBillingSupported(int apiVersion, String packageName, String type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides details of a list of SKUs
|
||||||
|
* Given a list of SKUs of a valid type in the skusBundle, this returns a bundle
|
||||||
|
* with a list JSON strings containing the productId, price, title and description.
|
||||||
|
* This API can be called with a maximum of 20 SKUs.
|
||||||
|
* @param apiVersion billing API version that the Third-party is using
|
||||||
|
* @param packageName the package name of the calling app
|
||||||
|
* @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST"
|
||||||
|
* @return Bundle containing the following key-value pairs
|
||||||
|
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
|
||||||
|
* failure as listed above.
|
||||||
|
* "DETAILS_LIST" with a StringArrayList containing purchase information
|
||||||
|
* in JSON format similar to:
|
||||||
|
* '{ "productId" : "exampleSku", "type" : "inapp", "price" : "$5.00",
|
||||||
|
* "title : "Example Title", "description" : "This is an example description" }'
|
||||||
|
*/
|
||||||
|
Bundle getSkuDetails(int apiVersion, String packageName, String type, in Bundle skusBundle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU,
|
||||||
|
* the type, a unique purchase token and an optional developer payload.
|
||||||
|
* @param apiVersion billing API version that the app is using
|
||||||
|
* @param packageName package name of the calling app
|
||||||
|
* @param sku the SKU of the in-app item as published in the developer console
|
||||||
|
* @param type the type of the in-app item ("inapp" for one-time purchases
|
||||||
|
* and "subs" for subscription).
|
||||||
|
* @param developerPayload optional argument to be sent back with the purchase information
|
||||||
|
* @return Bundle containing the following key-value pairs
|
||||||
|
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
|
||||||
|
* failure as listed above.
|
||||||
|
* "BUY_INTENT" - PendingIntent to start the purchase flow
|
||||||
|
*
|
||||||
|
* The Pending intent should be launched with startIntentSenderForResult. When purchase flow
|
||||||
|
* has completed, the onActivityResult() will give a resultCode of OK or CANCELED.
|
||||||
|
* If the purchase is successful, the result data will contain the following key-value pairs
|
||||||
|
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
|
||||||
|
* failure as listed above.
|
||||||
|
* "INAPP_PURCHASE_DATA" - String in JSON format similar to
|
||||||
|
* '{"orderId":"12999763169054705758.1371079406387615",
|
||||||
|
* "packageName":"com.example.app",
|
||||||
|
* "productId":"exampleSku",
|
||||||
|
* "purchaseTime":1345678900000,
|
||||||
|
* "purchaseToken" : "122333444455555",
|
||||||
|
* "developerPayload":"example developer payload" }'
|
||||||
|
* "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that
|
||||||
|
* was signed with the private key of the developer
|
||||||
|
* TODO: change this to app-specific keys.
|
||||||
|
*/
|
||||||
|
Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type,
|
||||||
|
String developerPayload);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current SKUs owned by the user of the type and package name specified along with
|
||||||
|
* purchase information and a signature of the data to be validated.
|
||||||
|
* This will return all SKUs that have been purchased in V3 and managed items purchased using
|
||||||
|
* V1 and V2 that have not been consumed.
|
||||||
|
* @param apiVersion billing API version that the app is using
|
||||||
|
* @param packageName package name of the calling app
|
||||||
|
* @param type the type of the in-app items being requested
|
||||||
|
* ("inapp" for one-time purchases and "subs" for subscription).
|
||||||
|
* @param continuationToken to be set as null for the first call, if the number of owned
|
||||||
|
* skus are too many, a continuationToken is returned in the response bundle.
|
||||||
|
* This method can be called again with the continuation token to get the next set of
|
||||||
|
* owned skus.
|
||||||
|
* @return Bundle containing the following key-value pairs
|
||||||
|
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
|
||||||
|
* failure as listed above.
|
||||||
|
* "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs
|
||||||
|
* "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information
|
||||||
|
* "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures
|
||||||
|
* of the purchase information
|
||||||
|
* "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the
|
||||||
|
* next set of in-app purchases. Only set if the
|
||||||
|
* user has more owned skus than the current list.
|
||||||
|
*/
|
||||||
|
Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume the last purchase of the given SKU. This will result in this item being removed
|
||||||
|
* from all subsequent responses to getPurchases() and allow re-purchase of this item.
|
||||||
|
* @param apiVersion billing API version that the app is using
|
||||||
|
* @param packageName package name of the calling app
|
||||||
|
* @param purchaseToken token in the purchase information JSON that identifies the purchase
|
||||||
|
* to be consumed
|
||||||
|
* @return 0 if consumption succeeded. Appropriate error values for failures.
|
||||||
|
*/
|
||||||
|
int consumePurchase(int apiVersion, String packageName, String purchaseToken);
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,7 @@
|
|||||||
package sharedcode.turboeditor.activity;
|
package sharedcode.turboeditor.activity;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.FragmentManager;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -30,20 +31,16 @@ import android.widget.ListView;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
import sharedcode.turboeditor.R;
|
||||||
import sharedcode.turboeditor.preferences.PreferenceHelper;
|
import sharedcode.turboeditor.util.ThemeUtils;
|
||||||
|
|
||||||
public class LicensesActivity extends Activity implements AdapterView.OnItemClickListener {
|
public class LicensesActivity extends Activity implements AdapterView.OnItemClickListener {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
ThemeUtils.setTheme(this);
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
boolean light = PreferenceHelper.getLightTheme(this);
|
|
||||||
if (light) {
|
|
||||||
setTheme(R.style.AppTheme_Light);
|
|
||||||
} else {
|
|
||||||
setTheme(R.style.AppTheme_Dark);
|
|
||||||
}
|
|
||||||
setContentView(R.layout.activity_licenses);
|
setContentView(R.layout.activity_licenses);
|
||||||
ListView listView = (ListView) findViewById(android.R.id.list);
|
ListView listView = (ListView) findViewById(android.R.id.list);
|
||||||
listView.setOnItemClickListener(this);
|
listView.setOnItemClickListener(this);
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sharedcode.turboeditor.activity;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.view.ViewConfiguration;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
public class MyApp extends Application {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
// force to sow the overflow menu icon
|
||||||
|
try {
|
||||||
|
ViewConfiguration config = ViewConfiguration.get(this);
|
||||||
|
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
|
||||||
|
if (menuKeyField != null) {
|
||||||
|
menuKeyField.setAccessible(true);
|
||||||
|
menuKeyField.setBoolean(config, false);
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,166 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sharedcode.turboeditor.activity;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
|
||||||
import sharedcode.turboeditor.util.AppInfoHelper;
|
|
||||||
import sharedcode.turboeditor.util.Constants;
|
|
||||||
import sharedcode.turboeditor.util.ProCheckUtils;
|
|
||||||
|
|
||||||
public class PreferenceAbout extends Activity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(final Bundle savedInstanceState) {
|
|
||||||
setTheme(R.style.AppTheme_Dark);
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_about);
|
|
||||||
|
|
||||||
TextView changeLogText = (TextView) findViewById(R.id.changelog_text);
|
|
||||||
TextView proVersionText = (TextView) findViewById(R.id.pro_version_text);
|
|
||||||
|
|
||||||
try {
|
|
||||||
changeLogText.setText(String.format(getString(R.string.app_version), getPackageManager().getPackageInfo(getPackageName(), 0).versionName));
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
proVersionText.setVisibility(ProCheckUtils.isPro(getBaseContext()) ? View.GONE : View.VISIBLE);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
//checkout.stop();
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OpenPlayStore(View view) {
|
|
||||||
try {
|
|
||||||
if (Constants.FOR_AMAZON) {
|
|
||||||
String url = "amzn://apps/android?p=com.maskyn.fileeditor";
|
|
||||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
|
||||||
} else {
|
|
||||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=pub:Maskyn"))
|
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GoToProVersion(View view) {
|
|
||||||
try {
|
|
||||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.maskyn.fileeditorpro"))
|
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OpenGithub(View view) {
|
|
||||||
String url = "https://github.com/vmihalachi/TurboEditor";
|
|
||||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SendFeedback(View view) {
|
|
||||||
String url = "http://forum.xda-developers.com/android/apps-games/app-turbo-editor-text-editor-t2832016";
|
|
||||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SendMail(View view) {
|
|
||||||
Intent i = new Intent(Intent.ACTION_SEND);
|
|
||||||
i.setType("message/rfc822");
|
|
||||||
i.putExtra(Intent.EXTRA_EMAIL, new String[]{"maskyngames@gmail.com"});
|
|
||||||
i.putExtra(Intent.EXTRA_SUBJECT, AppInfoHelper.getApplicationName(getBaseContext()) + " " + AppInfoHelper.getCurrentVersion(getBaseContext()));
|
|
||||||
i.putExtra(Intent.EXTRA_TEXT, "");
|
|
||||||
try {
|
|
||||||
startActivity(Intent.createChooser(i, getString(R.string.nome_app_turbo_editor)));
|
|
||||||
} catch (android.content.ActivityNotFoundException ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OpenTranslatePage(View view) {
|
|
||||||
String url = "http://crowdin.net/project/turbo-client";
|
|
||||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OpenGooglePlusCommunity(View view) {
|
|
||||||
String url = "https://plus.google.com/u/0/communities/111974095419108178946";
|
|
||||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*void setupClickablePreferences() {
|
|
||||||
final Preference email = findPreference("aboutactivity_authoremail"),
|
|
||||||
changelog = findPreference("aboutactivity_changelog"),
|
|
||||||
open_source_licenses = findPreference("aboutactivity_open_source_licenses"),
|
|
||||||
market = findPreference("aboutactivity_authormarket");
|
|
||||||
if (email != null) {
|
|
||||||
email.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceClick(final Preference preference) {
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (changelog != null) {
|
|
||||||
changelog.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceClick(final Preference preference) {
|
|
||||||
ChangelogDialogFragment.showChangeLogDialog(getFragmentManager());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (open_source_licenses != null) {
|
|
||||||
open_source_licenses.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceClick(final Preference preference) {
|
|
||||||
startActivity(new Intent(PreferenceAbout.this, LicensesActivity.class));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (market != null) {
|
|
||||||
market.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceClick(final Preference preference) {
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
|
@ -19,29 +19,25 @@
|
|||||||
|
|
||||||
package sharedcode.turboeditor.activity;
|
package sharedcode.turboeditor.activity;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.view.MenuItemCompat;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
|
import android.support.v7.widget.SearchView;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.Filter;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.SearchView;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.faizmalkani.floatingactionbutton.FloatingActionButton;
|
import com.faizmalkani.floatingactionbutton.FloatingActionButton;
|
||||||
import sharedcode.turboeditor.R;
|
|
||||||
import sharedcode.turboeditor.adapter.AdapterDetailedList;
|
|
||||||
import sharedcode.turboeditor.fragment.EditDialogFragment;
|
|
||||||
import sharedcode.turboeditor.util.AlphanumComparator;
|
|
||||||
import sharedcode.turboeditor.util.Constants;
|
|
||||||
import sharedcode.turboeditor.preferences.PreferenceHelper;
|
|
||||||
import sharedcode.turboeditor.util.RootUtils;
|
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
@ -57,28 +53,36 @@ import java.util.Comparator;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
public class SelectFileActivity extends Activity implements SearchView.OnQueryTextListener, AdapterView.OnItemClickListener, EditDialogFragment.EditDialogListener {
|
import sharedcode.turboeditor.R;
|
||||||
private String currentFolder;
|
import sharedcode.turboeditor.adapter.AdapterDetailedList;
|
||||||
|
import sharedcode.turboeditor.fragment.EditTextDialog;
|
||||||
|
import sharedcode.turboeditor.preferences.PreferenceHelper;
|
||||||
|
import sharedcode.turboeditor.root.RootUtils;
|
||||||
|
import sharedcode.turboeditor.util.AlphanumComparator;
|
||||||
|
import sharedcode.turboeditor.util.Build;
|
||||||
|
import sharedcode.turboeditor.util.ThemeUtils;
|
||||||
|
|
||||||
|
public class SelectFileActivity extends ActionBarActivity implements SearchView.OnQueryTextListener, AdapterView.OnItemClickListener, EditTextDialog.EditDialogListener {
|
||||||
|
private String currentFolder = PreferenceHelper.SD_CARD_ROOT;
|
||||||
private ListView listView;
|
private ListView listView;
|
||||||
private boolean wantAFile;
|
private boolean wantAFile = true;
|
||||||
private MenuItem mSearchViewMenuItem;
|
private MenuItem mSearchViewMenuItem;
|
||||||
private SearchView mSearchView;
|
private SearchView mSearchView;
|
||||||
|
private Filter filter;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
|
||||||
boolean light = PreferenceHelper.getLightTheme(this);
|
ThemeUtils.setTheme(this);
|
||||||
if (light) {
|
|
||||||
setTheme(R.style.AppTheme_Light);
|
|
||||||
} else {
|
|
||||||
setTheme(R.style.AppTheme_Dark);
|
|
||||||
}
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_select_file);
|
setContentView(R.layout.activity_select_file);
|
||||||
|
|
||||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
final Actions action = (Actions) getIntent().getExtras().getSerializable("action");
|
final Actions action = (Actions) getIntent().getExtras().getSerializable("action");
|
||||||
wantAFile = action == Actions.SelectFile;
|
wantAFile = action == Actions.SelectFile;
|
||||||
@ -87,7 +91,7 @@ public class SelectFileActivity extends Activity implements SearchView.OnQueryTe
|
|||||||
listView.setOnItemClickListener(this);
|
listView.setOnItemClickListener(this);
|
||||||
listView.setTextFilterEnabled(true);
|
listView.setTextFilterEnabled(true);
|
||||||
|
|
||||||
FloatingActionButton mFab = (FloatingActionButton)findViewById(R.id.fabbutton);
|
FloatingActionButton mFab = (FloatingActionButton) findViewById(R.id.fabbutton);
|
||||||
mFab.setColor(getResources().getColor(R.color.fab_light));
|
mFab.setColor(getResources().getColor(R.color.fab_light));
|
||||||
mFab.setDrawable(getResources().getDrawable(R.drawable.ic_fab_add));
|
mFab.setDrawable(getResources().getDrawable(R.drawable.ic_fab_add));
|
||||||
|
|
||||||
@ -101,14 +105,14 @@ public class SelectFileActivity extends Activity implements SearchView.OnQueryTe
|
|||||||
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemClick(MenuItem item) {
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
final EditDialogFragment dialogFrag;
|
final EditTextDialog dialogFrag;
|
||||||
int i = item.getItemId();
|
int i = item.getItemId();
|
||||||
if (i == R.id.im_new_file) {
|
if (i == R.id.im_new_file) {
|
||||||
dialogFrag = EditDialogFragment.newInstance(EditDialogFragment.Actions.NewFile);
|
dialogFrag = EditTextDialog.newInstance(EditTextDialog.Actions.NewFile);
|
||||||
dialogFrag.show(getFragmentManager().beginTransaction(), "dialog");
|
dialogFrag.show(getFragmentManager().beginTransaction(), "dialog");
|
||||||
return true;
|
return true;
|
||||||
} else if (i == R.id.im_new_folder) {
|
} else if (i == R.id.im_new_folder) {
|
||||||
dialogFrag = EditDialogFragment.newInstance(EditDialogFragment.Actions.NewFolder);
|
dialogFrag = EditTextDialog.newInstance(EditTextDialog.Actions.NewFolder);
|
||||||
dialogFrag.show(getFragmentManager().beginTransaction(), "dialog");
|
dialogFrag.show(getFragmentManager().beginTransaction(), "dialog");
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -147,10 +151,13 @@ public class SelectFileActivity extends Activity implements SearchView.OnQueryTe
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean onQueryTextChange(String newText) {
|
public boolean onQueryTextChange(String newText) {
|
||||||
|
if (filter == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (TextUtils.isEmpty(newText)) {
|
if (TextUtils.isEmpty(newText)) {
|
||||||
listView.clearTextFilter();
|
filter.filter(null);
|
||||||
} else {
|
} else {
|
||||||
listView.setFilterText(newText);
|
filter.filter(newText);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -205,7 +212,7 @@ public class SelectFileActivity extends Activity implements SearchView.OnQueryTe
|
|||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
getMenuInflater().inflate(R.menu.activity_select_file, menu);
|
getMenuInflater().inflate(R.menu.activity_select_file, menu);
|
||||||
mSearchViewMenuItem = menu.findItem(R.id.im_search);
|
mSearchViewMenuItem = menu.findItem(R.id.im_search);
|
||||||
mSearchView = (SearchView) mSearchViewMenuItem.getActionView();
|
mSearchView = (SearchView) MenuItemCompat.getActionView(mSearchViewMenuItem);
|
||||||
mSearchView.setIconifiedByDefault(true);
|
mSearchView.setIconifiedByDefault(true);
|
||||||
mSearchView.setOnQueryTextListener(this);
|
mSearchView.setOnQueryTextListener(this);
|
||||||
mSearchView.setSubmitButtonEnabled(false);
|
mSearchView.setSubmitButtonEnabled(false);
|
||||||
@ -218,15 +225,15 @@ public class SelectFileActivity extends Activity implements SearchView.OnQueryTe
|
|||||||
MenuItem imSetAsWorkingFolder = menu.findItem(R.id.im_set_as_working_folder);
|
MenuItem imSetAsWorkingFolder = menu.findItem(R.id.im_set_as_working_folder);
|
||||||
MenuItem imIsWorkingFolder = menu.findItem(R.id.im_is_working_folder);
|
MenuItem imIsWorkingFolder = menu.findItem(R.id.im_is_working_folder);
|
||||||
MenuItem imSelectFolder = menu.findItem(R.id.im_select_folder);
|
MenuItem imSelectFolder = menu.findItem(R.id.im_select_folder);
|
||||||
if(imSetAsWorkingFolder != null){
|
if (imSetAsWorkingFolder != null) {
|
||||||
// set the imSetAsWorkingFolder visible only if the two folder dont concide
|
// set the imSetAsWorkingFolder visible only if the two folder dont concide
|
||||||
imSetAsWorkingFolder.setVisible(!currentFolder.equals(PreferenceHelper.getWorkingFolder(SelectFileActivity.this)));
|
imSetAsWorkingFolder.setVisible(!currentFolder.equals(PreferenceHelper.getWorkingFolder(SelectFileActivity.this)));
|
||||||
}
|
}
|
||||||
if(imIsWorkingFolder != null) {
|
if (imIsWorkingFolder != null) {
|
||||||
// set visible is the other is invisible
|
// set visible is the other is invisible
|
||||||
imIsWorkingFolder.setVisible(!imSetAsWorkingFolder.isVisible());
|
imIsWorkingFolder.setVisible(!imSetAsWorkingFolder.isVisible());
|
||||||
}
|
}
|
||||||
if(imSelectFolder != null) {
|
if (imSelectFolder != null) {
|
||||||
imSelectFolder.setVisible(!wantAFile);
|
imSelectFolder.setVisible(!wantAFile);
|
||||||
}
|
}
|
||||||
return super.onPrepareOptionsMenu(menu);
|
return super.onPrepareOptionsMenu(menu);
|
||||||
@ -242,6 +249,9 @@ public class SelectFileActivity extends Activity implements SearchView.OnQueryTe
|
|||||||
PreferenceHelper.setWorkingFolder(SelectFileActivity.this, currentFolder);
|
PreferenceHelper.setWorkingFolder(SelectFileActivity.this, currentFolder);
|
||||||
invalidateOptionsMenu();
|
invalidateOptionsMenu();
|
||||||
return true;
|
return true;
|
||||||
|
} else if (i == R.id.im_is_working_folder) {
|
||||||
|
Toast.makeText(getBaseContext(), R.string.is_the_working_folder, Toast.LENGTH_SHORT).show();
|
||||||
|
return true;
|
||||||
} else if (i == R.id.im_select_folder) {
|
} else if (i == R.id.im_select_folder) {
|
||||||
returnData(currentFolder);
|
returnData(currentFolder);
|
||||||
return true;
|
return true;
|
||||||
@ -251,11 +261,11 @@ public class SelectFileActivity extends Activity implements SearchView.OnQueryTe
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFinishEditDialog(final String inputText, final String hint, final EditDialogFragment.Actions actions) {
|
public void onFinishEditDialog(final String inputText, final String hint, final EditTextDialog.Actions actions) {
|
||||||
if (actions == EditDialogFragment.Actions.NewFile && !TextUtils.isEmpty(inputText)) {
|
if (actions == EditTextDialog.Actions.NewFile && !TextUtils.isEmpty(inputText)) {
|
||||||
File file = new File(currentFolder, inputText);
|
File file = new File(currentFolder, inputText);
|
||||||
returnData(file.getAbsolutePath());
|
returnData(file.getAbsolutePath());
|
||||||
} else if (actions == EditDialogFragment.Actions.NewFolder && !TextUtils.isEmpty(inputText)) {
|
} else if (actions == EditTextDialog.Actions.NewFolder && !TextUtils.isEmpty(inputText)) {
|
||||||
File file = new File(currentFolder, inputText);
|
File file = new File(currentFolder, inputText);
|
||||||
file.mkdirs();
|
file.mkdirs();
|
||||||
new UpdateList().execute(currentFolder);
|
new UpdateList().execute(currentFolder);
|
||||||
@ -275,7 +285,7 @@ public class SelectFileActivity extends Activity implements SearchView.OnQueryTe
|
|||||||
super.onPreExecute();
|
super.onPreExecute();
|
||||||
if (mSearchView != null) {
|
if (mSearchView != null) {
|
||||||
mSearchView.setIconified(true);
|
mSearchView.setIconified(true);
|
||||||
mSearchViewMenuItem.collapseActionView();
|
MenuItemCompat.collapseActionView(mSearchViewMenuItem);
|
||||||
mSearchView.setQuery("", false);
|
mSearchView.setQuery("", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,8 +339,8 @@ public class SelectFileActivity extends Activity implements SearchView.OnQueryTe
|
|||||||
getString(R.string.folder),
|
getString(R.string.folder),
|
||||||
""));
|
""));
|
||||||
} else if (f.isFile()
|
} else if (f.isFile()
|
||||||
&& !FilenameUtils.isExtension(f.getName().toLowerCase(), unopenableExtensions)
|
&& !FilenameUtils.isExtension(f.getName().toLowerCase(), unopenableExtensions)
|
||||||
&& FileUtils.sizeOf(f) <= Constants.MAX_FILE_SIZE * FileUtils.ONE_KB) {
|
&& FileUtils.sizeOf(f) <= Build.MAX_FILE_SIZE * FileUtils.ONE_KB) {
|
||||||
final long fileSize = f.length();
|
final long fileSize = f.length();
|
||||||
SimpleDateFormat format = new SimpleDateFormat("MMM dd, yyyy hh:mm a");
|
SimpleDateFormat format = new SimpleDateFormat("MMM dd, yyyy hh:mm a");
|
||||||
String date = format.format(f.lastModified());
|
String date = format.format(f.lastModified());
|
||||||
@ -357,6 +367,7 @@ public class SelectFileActivity extends Activity implements SearchView.OnQueryTe
|
|||||||
boolean isRoot = currentFolder.equals("/");
|
boolean isRoot = currentFolder.equals("/");
|
||||||
AdapterDetailedList mAdapter = new AdapterDetailedList(getBaseContext(), names, isRoot);
|
AdapterDetailedList mAdapter = new AdapterDetailedList(getBaseContext(), names, isRoot);
|
||||||
listView.setAdapter(mAdapter);
|
listView.setAdapter(mAdapter);
|
||||||
|
filter = mAdapter.getFilter();
|
||||||
} else if (exceptionMessage != null) {
|
} else if (exceptionMessage != null) {
|
||||||
Toast.makeText(SelectFileActivity.this, exceptionMessage, Toast.LENGTH_SHORT).show();
|
Toast.makeText(SelectFileActivity.this, exceptionMessage, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
@ -29,14 +29,14 @@ import android.widget.Filter;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
|
||||||
import sharedcode.turboeditor.util.MimeTypes;
|
|
||||||
|
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
import sharedcode.turboeditor.R;
|
||||||
|
import sharedcode.turboeditor.util.MimeTypes;
|
||||||
|
|
||||||
public class AdapterDetailedList extends
|
public class AdapterDetailedList extends
|
||||||
ArrayAdapter<AdapterDetailedList.FileDetail> {
|
ArrayAdapter<AdapterDetailedList.FileDetail> {
|
||||||
|
|
||||||
|
@ -29,10 +29,10 @@ import android.widget.ArrayAdapter;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.List;
|
||||||
|
|
||||||
|
import sharedcode.turboeditor.R;
|
||||||
|
|
||||||
public class AdapterDrawer extends
|
public class AdapterDrawer extends
|
||||||
ArrayAdapter<File> {
|
ArrayAdapter<File> {
|
||||||
@ -41,11 +41,11 @@ public class AdapterDrawer extends
|
|||||||
// Layout Inflater
|
// Layout Inflater
|
||||||
private final LayoutInflater inflater;
|
private final LayoutInflater inflater;
|
||||||
// List of file details
|
// List of file details
|
||||||
private final ArrayList<File> files;
|
private final List<File> files;
|
||||||
private String selectedPath = "";
|
private String selectedPath = "";
|
||||||
|
|
||||||
public AdapterDrawer(Context context,
|
public AdapterDrawer(Context context,
|
||||||
ArrayList<File> files,
|
List<File> files,
|
||||||
Callbacks callbacks) {
|
Callbacks callbacks) {
|
||||||
super(context, R.layout.item_file_list, files);
|
super(context, R.layout.item_file_list, files);
|
||||||
this.files = files;
|
this.files = files;
|
||||||
@ -78,10 +78,13 @@ public class AdapterDrawer extends
|
|||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (TextUtils.equals(selectedPath, files.get(position).getAbsolutePath()))
|
|
||||||
hold.nameLabel.setTypeface(hold.nameLabel.getTypeface(), Typeface.BOLD);
|
if (TextUtils.equals(selectedPath, files.get(position).getAbsolutePath())) {
|
||||||
else
|
hold.nameLabel.setTypeface(null, Typeface.BOLD);
|
||||||
hold.nameLabel.setTypeface(hold.nameLabel.getTypeface(), Typeface.NORMAL);
|
} else {
|
||||||
|
hold.nameLabel.setTypeface(null, Typeface.NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
final ViewHolder hold = ((ViewHolder) convertView.getTag());
|
final ViewHolder hold = ((ViewHolder) convertView.getTag());
|
||||||
final String fileName = files.get(position).getName();
|
final String fileName = files.get(position).getName();
|
||||||
@ -95,23 +98,26 @@ public class AdapterDrawer extends
|
|||||||
selectedPath = "";
|
selectedPath = "";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (TextUtils.equals(selectedPath, files.get(position).getAbsolutePath()))
|
|
||||||
hold.nameLabel.setTypeface(hold.nameLabel.getTypeface(), Typeface.BOLD);
|
if (TextUtils.equals(selectedPath, files.get(position).getAbsolutePath())) {
|
||||||
else
|
hold.nameLabel.setTypeface(null, Typeface.BOLD);
|
||||||
hold.nameLabel.setTypeface(hold.nameLabel.getTypeface(), Typeface.NORMAL);
|
} else {
|
||||||
|
hold.nameLabel.setTypeface(null, Typeface.NORMAL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return convertView;
|
return convertView;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectView(String selectedPath) {
|
public void selectView(String selectedPath) {
|
||||||
callbacks.ItemSelected(selectedPath);
|
//callbacks.ItemSelected(selectedPath);
|
||||||
this.selectedPath = selectedPath;
|
this.selectedPath = selectedPath;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Callbacks {
|
public interface Callbacks {
|
||||||
void CancelItem(int position, boolean andCloseOpenedFile);
|
void CancelItem(int position, boolean andCloseOpenedFile);
|
||||||
void ItemSelected(String path);
|
|
||||||
|
//void ItemSelected(String path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ViewHolder {
|
public static class ViewHolder {
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sharedcode.turboeditor.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import sharedcode.turboeditor.R;
|
||||||
|
|
||||||
|
public class AdapterTwoItem extends
|
||||||
|
ArrayAdapter<String> {
|
||||||
|
|
||||||
|
private final LayoutInflater inflater;
|
||||||
|
private final String[] lines1;
|
||||||
|
private final String[] lines2;
|
||||||
|
|
||||||
|
public AdapterTwoItem(Context context,
|
||||||
|
String[] lines1,
|
||||||
|
String[] lines2) {
|
||||||
|
super(context, R.layout.item_two_lines, lines1);
|
||||||
|
this.lines1 = lines1;
|
||||||
|
this.lines2 = lines2;
|
||||||
|
this.inflater = LayoutInflater.from(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(final int position,
|
||||||
|
View convertView, final ViewGroup parent) {
|
||||||
|
if (convertView == null) {
|
||||||
|
convertView = this.inflater
|
||||||
|
.inflate(R.layout.item_two_lines,
|
||||||
|
parent, false);
|
||||||
|
final ViewHolder hold = new ViewHolder();
|
||||||
|
hold.line1 = (TextView) convertView.findViewById(android.R.id.text1);
|
||||||
|
hold.line2 = (TextView) convertView.findViewById(android.R.id.text2);
|
||||||
|
convertView.setTag(hold);
|
||||||
|
|
||||||
|
hold.line1.setText(lines1[position]);
|
||||||
|
hold.line2.setText(lines2[position]);
|
||||||
|
} else {
|
||||||
|
final ViewHolder hold = ((ViewHolder) convertView.getTag());
|
||||||
|
hold.line1.setText(lines1[position]);
|
||||||
|
hold.line2.setText(lines2[position]);
|
||||||
|
}
|
||||||
|
return convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ViewHolder {
|
||||||
|
|
||||||
|
public TextView line1;
|
||||||
|
public TextView line2;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package sharedcode.turboeditor.fragment;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.app.DialogFragment;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import sharedcode.turboeditor.R;
|
||||||
|
import sharedcode.turboeditor.views.DialogHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog fragment that shows some info about this application.
|
||||||
|
*
|
||||||
|
* @author Artem Chepurnoy
|
||||||
|
*/
|
||||||
|
public class AboutDialog extends DialogFragment {
|
||||||
|
|
||||||
|
private static final String VERSION_UNAVAILABLE = "N/A";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges app name and version name into one.
|
||||||
|
*/
|
||||||
|
public static CharSequence getVersionName(Context context) {
|
||||||
|
PackageManager pm = context.getPackageManager();
|
||||||
|
String packageName = context.getPackageName();
|
||||||
|
String versionName;
|
||||||
|
try {
|
||||||
|
PackageInfo info = pm.getPackageInfo(packageName, 0);
|
||||||
|
versionName = info.versionName;
|
||||||
|
|
||||||
|
// Make the info part of version name a bit smaller.
|
||||||
|
if (versionName.indexOf('-') >= 0) {
|
||||||
|
versionName = versionName.replaceFirst("\\-", "<small>-") + "</small>";
|
||||||
|
}
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
versionName = VERSION_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resources res = context.getResources();
|
||||||
|
return Html.fromHtml(
|
||||||
|
res.getString(R.string.about_title,
|
||||||
|
res.getString(R.string.nome_app_turbo_editor), versionName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
Context context = getActivity();
|
||||||
|
assert context != null;
|
||||||
|
|
||||||
|
CharSequence message = Html.fromHtml(getString(
|
||||||
|
R.string.about_message));
|
||||||
|
|
||||||
|
View view = new DialogHelper.Builder(context)
|
||||||
|
.setIcon(getResources().getDrawable(R.drawable.ic_launcher))
|
||||||
|
.setTitle(getVersionName(context))
|
||||||
|
.setMessage(message)
|
||||||
|
.createCommonView();
|
||||||
|
|
||||||
|
return new AlertDialog.Builder(context)
|
||||||
|
.setView(view)
|
||||||
|
.setNeutralButton(R.string.close, null)
|
||||||
|
.create();
|
||||||
|
}
|
||||||
|
}
|
@ -31,22 +31,21 @@ import android.net.Uri;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
|
||||||
|
|
||||||
import it.gmariotti.changelibs.library.view.ChangeLogListView;
|
import it.gmariotti.changelibs.library.view.ChangeLogListView;
|
||||||
import sharedcode.turboeditor.util.Constants;
|
import sharedcode.turboeditor.R;
|
||||||
|
import sharedcode.turboeditor.util.Build;
|
||||||
|
|
||||||
public class ChangelogDialogFragment extends DialogFragment {
|
public class ChangelogDialog extends DialogFragment {
|
||||||
|
|
||||||
public static void showChangeLogDialog(FragmentManager fragmentManager) {
|
public static void showChangeLogDialog(FragmentManager fragmentManager) {
|
||||||
ChangelogDialogFragment changelogDialogFragment = new ChangelogDialogFragment();
|
ChangelogDialog changelogDialog = new ChangelogDialog();
|
||||||
FragmentTransaction ft = fragmentManager.beginTransaction();
|
FragmentTransaction ft = fragmentManager.beginTransaction();
|
||||||
Fragment prev = fragmentManager.findFragmentByTag("changelogdemo_dialog");
|
Fragment prev = fragmentManager.findFragmentByTag("changelogdemo_dialog");
|
||||||
if (prev != null) {
|
if (prev != null) {
|
||||||
ft.remove(prev);
|
ft.remove(prev);
|
||||||
}
|
}
|
||||||
ft.addToBackStack(null);
|
ft.addToBackStack(null);
|
||||||
changelogDialogFragment.show(ft, "changelogdemo_dialog");
|
changelogDialog.show(ft, "changelogdemo_dialog");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -73,7 +72,7 @@ public class ChangelogDialogFragment extends DialogFragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(final DialogInterface dialog, final int which) {
|
public void onClick(final DialogInterface dialog, final int which) {
|
||||||
try {
|
try {
|
||||||
if (Constants.FOR_AMAZON) {
|
if (Build.FOR_AMAZON) {
|
||||||
String url = "amzn://apps/android?p=com.maskyn.fileeditor";
|
String url = "amzn://apps/android?p=com.maskyn.fileeditor";
|
||||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
@ -32,18 +32,19 @@ import android.widget.EditText;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
import sharedcode.turboeditor.R;
|
||||||
|
import sharedcode.turboeditor.views.DialogHelper;
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
public class EditDialogFragment extends DialogFragment implements TextView.OnEditorActionListener {
|
public class EditTextDialog extends DialogFragment implements TextView.OnEditorActionListener {
|
||||||
|
|
||||||
private EditText mEditText;
|
private EditText mEditText;
|
||||||
|
|
||||||
public static EditDialogFragment newInstance(final Actions action) {
|
public static EditTextDialog newInstance(final Actions action) {
|
||||||
return EditDialogFragment.newInstance(action, "");
|
return EditTextDialog.newInstance(action, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EditDialogFragment newInstance(final Actions action, final String hint) {
|
public static EditTextDialog newInstance(final Actions action, final String hint) {
|
||||||
final EditDialogFragment f = new EditDialogFragment();
|
final EditTextDialog f = new EditTextDialog();
|
||||||
final Bundle args = new Bundle();
|
final Bundle args = new Bundle();
|
||||||
args.putSerializable("action", action);
|
args.putSerializable("action", action);
|
||||||
args.putString("hint", hint);
|
args.putString("hint", hint);
|
||||||
@ -55,22 +56,25 @@ public class EditDialogFragment extends DialogFragment implements TextView.OnEdi
|
|||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
|
||||||
final Actions action = (Actions) getArguments().getSerializable("action");
|
final Actions action = (Actions) getArguments().getSerializable("action");
|
||||||
final String hint;
|
final String title;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case NewFile:
|
case NewFile:
|
||||||
hint = getString(R.string.file);
|
title = getString(R.string.file);
|
||||||
break;
|
break;
|
||||||
case NewFolder:
|
case NewFolder:
|
||||||
hint = getString(R.string.folder);
|
title = getString(R.string.folder);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
hint = null;
|
title = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_fragment_edittext, null);
|
View view = new DialogHelper.Builder(getActivity())
|
||||||
|
.setTitle(title)
|
||||||
|
.setView(R.layout.dialog_fragment_edittext)
|
||||||
|
.createSkeletonView();
|
||||||
this.mEditText = (EditText) view.findViewById(android.R.id.edit);
|
this.mEditText = (EditText) view.findViewById(android.R.id.edit);
|
||||||
this.mEditText.setHint(hint);
|
this.mEditText.setHint(R.string.name);
|
||||||
|
|
||||||
// Show soft keyboard automatically
|
// Show soft keyboard automatically
|
||||||
this.mEditText.setText(getArguments().getString("hint"));
|
this.mEditText.setText(getArguments().getString("hint"));
|
File diff suppressed because it is too large
Load Diff
@ -22,25 +22,20 @@ package sharedcode.turboeditor.fragment;
|
|||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.DialogFragment;
|
import android.app.DialogFragment;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.support.v7.widget.SwitchCompat;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.CompoundButton;
|
import android.widget.CompoundButton;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.Switch;
|
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
|
||||||
import sharedcode.turboeditor.preferences.PreferenceHelper;
|
|
||||||
import sharedcode.turboeditor.preferences.SettingsFragment;
|
|
||||||
import sharedcode.turboeditor.util.SaveFileTask;
|
|
||||||
|
|
||||||
import org.mozilla.universalchardet.Constants;
|
import org.mozilla.universalchardet.Constants;
|
||||||
|
|
||||||
public class EncodingDialogFragment extends DialogFragment implements AdapterView.OnItemClickListener {
|
import sharedcode.turboeditor.R;
|
||||||
|
import sharedcode.turboeditor.preferences.PreferenceHelper;
|
||||||
|
|
||||||
|
public class EncodingDialog extends DialogFragment implements AdapterView.OnItemClickListener {
|
||||||
|
|
||||||
private final String[] encodings = new String[]{
|
private final String[] encodings = new String[]{
|
||||||
Constants.CHARSET_BIG5,
|
Constants.CHARSET_BIG5,
|
||||||
@ -72,8 +67,8 @@ public class EncodingDialogFragment extends DialogFragment implements AdapterVie
|
|||||||
};
|
};
|
||||||
private ListView list;
|
private ListView list;
|
||||||
|
|
||||||
public static EncodingDialogFragment newInstance() {
|
public static EncodingDialog newInstance() {
|
||||||
final EncodingDialogFragment f = new EncodingDialogFragment();
|
final EncodingDialog f = new EncodingDialog();
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +77,7 @@ public class EncodingDialogFragment extends DialogFragment implements AdapterVie
|
|||||||
|
|
||||||
final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_encoding_list, null);
|
final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_encoding_list, null);
|
||||||
list = (ListView) view.findViewById(android.R.id.list);
|
list = (ListView) view.findViewById(android.R.id.list);
|
||||||
Switch autoencoding = (Switch) view.findViewById(android.R.id.checkbox);
|
SwitchCompat autoencoding = (SwitchCompat) view.findViewById(android.R.id.checkbox);
|
||||||
autoencoding.setChecked(PreferenceHelper.getAutoEncoding(getActivity()));
|
autoencoding.setChecked(PreferenceHelper.getAutoEncoding(getActivity()));
|
||||||
|
|
||||||
autoencoding.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
autoencoding.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sharedcode.turboeditor.fragment;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.app.DialogFragment;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ListView;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import sharedcode.turboeditor.R;
|
||||||
|
import sharedcode.turboeditor.adapter.AdapterTwoItem;
|
||||||
|
import sharedcode.turboeditor.views.DialogHelper;
|
||||||
|
|
||||||
|
// ...
|
||||||
|
public class FileInfoDialog extends DialogFragment {
|
||||||
|
|
||||||
|
public static FileInfoDialog newInstance(String filePath) {
|
||||||
|
final FileInfoDialog f = new FileInfoDialog();
|
||||||
|
final Bundle args = new Bundle();
|
||||||
|
args.putString("filePath", filePath);
|
||||||
|
f.setArguments(args);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
View view = new DialogHelper.Builder(getActivity())
|
||||||
|
.setTitle(R.string.info)
|
||||||
|
.setView(R.layout.dialog_fragment_file_info)
|
||||||
|
.createSkeletonView();
|
||||||
|
//final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_fragment_file_info, null);
|
||||||
|
|
||||||
|
ListView list = (ListView) view.findViewById(android.R.id.list);
|
||||||
|
|
||||||
|
File file = new File(getArguments().getString("filePath"));
|
||||||
|
|
||||||
|
// Get the last modification information.
|
||||||
|
Long lastModified = file.lastModified();
|
||||||
|
|
||||||
|
// Create a new date object and pass last modified information
|
||||||
|
// to the date object.
|
||||||
|
Date date = new Date(lastModified);
|
||||||
|
|
||||||
|
String[] lines1 = {
|
||||||
|
getString(R.string.name),
|
||||||
|
getString(R.string.folder),
|
||||||
|
getString(R.string.size),
|
||||||
|
getString(R.string.modification_date)
|
||||||
|
};
|
||||||
|
String[] lines2 = {
|
||||||
|
file.getName(),
|
||||||
|
file.getParent(),
|
||||||
|
FileUtils.byteCountToDisplaySize(file.length()),
|
||||||
|
date.toString()
|
||||||
|
};
|
||||||
|
|
||||||
|
list.setAdapter(new AdapterTwoItem(getActivity(), lines1, lines2));
|
||||||
|
|
||||||
|
|
||||||
|
return new AlertDialog.Builder(getActivity())
|
||||||
|
.setView(view)
|
||||||
|
.setPositiveButton(android.R.string.ok,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.create();
|
||||||
|
}
|
||||||
|
}
|
@ -32,22 +32,22 @@ import android.widget.CompoundButton;
|
|||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
|
||||||
|
|
||||||
import sharedcode.turboeditor.util.SearchResult;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import sharedcode.turboeditor.R;
|
||||||
|
import sharedcode.turboeditor.texteditor.SearchResult;
|
||||||
|
import sharedcode.turboeditor.views.DialogHelper;
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
public class FindTextDialogFragment extends DialogFragment {
|
public class FindTextDialog extends DialogFragment {
|
||||||
|
|
||||||
private EditText textToFind, textToReplace;
|
private EditText textToFind, textToReplace;
|
||||||
private CheckBox regexCheck, replaceCheck, matchCaseCheck;
|
private CheckBox regexCheck, replaceCheck, matchCaseCheck;
|
||||||
|
|
||||||
public static FindTextDialogFragment newInstance(String allText) {
|
public static FindTextDialog newInstance(String allText) {
|
||||||
final FindTextDialogFragment f = new FindTextDialogFragment();
|
final FindTextDialog f = new FindTextDialog();
|
||||||
final Bundle args = new Bundle();
|
final Bundle args = new Bundle();
|
||||||
args.putString("allText", allText);
|
args.putString("allText", allText);
|
||||||
f.setArguments(args);
|
f.setArguments(args);
|
||||||
@ -57,7 +57,13 @@ public class FindTextDialogFragment extends DialogFragment {
|
|||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
|
||||||
final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_fragment_find_text, null);
|
//final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_fragment_find_text, null);
|
||||||
|
|
||||||
|
View view = new DialogHelper.Builder(getActivity())
|
||||||
|
.setTitle(R.string.find)
|
||||||
|
.setView(R.layout.dialog_fragment_find_text)
|
||||||
|
.createSkeletonView();
|
||||||
|
|
||||||
this.textToFind = (EditText) view.findViewById(R.id.text_to_find);
|
this.textToFind = (EditText) view.findViewById(R.id.text_to_find);
|
||||||
this.textToReplace = (EditText) view.findViewById(R.id.text_to_replace);
|
this.textToReplace = (EditText) view.findViewById(R.id.text_to_replace);
|
||||||
this.regexCheck = (CheckBox) view.findViewById(R.id.regex_check);
|
this.regexCheck = (CheckBox) view.findViewById(R.id.regex_check);
|
||||||
@ -80,41 +86,29 @@ public class FindTextDialogFragment extends DialogFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.setNegativeButton(android.R.string.cancel,
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.create();
|
.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart()
|
public void onStart() {
|
||||||
{
|
|
||||||
super.onStart(); //super.onStart() is where dialog.show() is actually called on the underlying dialog, so we have to do it after this point
|
super.onStart(); //super.onStart() is where dialog.show() is actually called on the underlying dialog, so we have to do it after this point
|
||||||
AlertDialog d = (AlertDialog)getDialog();
|
AlertDialog d = (AlertDialog) getDialog();
|
||||||
if(d != null)
|
if (d != null) {
|
||||||
{
|
|
||||||
Button positiveButton = (Button) d.getButton(Dialog.BUTTON_POSITIVE);
|
Button positiveButton = (Button) d.getButton(Dialog.BUTTON_POSITIVE);
|
||||||
positiveButton.setText(getString(R.string.find));
|
positiveButton.setText(getString(R.string.find));
|
||||||
positiveButton.setOnClickListener(new View.OnClickListener()
|
positiveButton.setOnClickListener(new View.OnClickListener() {
|
||||||
{
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v)
|
public void onClick(View v) {
|
||||||
{
|
|
||||||
returnData();
|
returnData();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Button negativeButton = (Button) d.getButton(Dialog.BUTTON_NEGATIVE);
|
Button negativeButton = (Button) d.getButton(Dialog.BUTTON_NEGATIVE);
|
||||||
negativeButton.setText(getString(android.R.string.cancel));
|
negativeButton.setText(getString(android.R.string.cancel));
|
||||||
negativeButton.setOnClickListener(new View.OnClickListener()
|
negativeButton.setOnClickListener(new View.OnClickListener() {
|
||||||
{
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v)
|
public void onClick(View v) {
|
||||||
{
|
|
||||||
dismiss();
|
dismiss();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -122,7 +116,7 @@ public class FindTextDialogFragment extends DialogFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void returnData() {
|
void returnData() {
|
||||||
if(textToFind.getText().toString().isEmpty()) {
|
if (textToFind.getText().toString().isEmpty()) {
|
||||||
this.dismiss();
|
this.dismiss();
|
||||||
} else {
|
} else {
|
||||||
// we disable the okButton while we search
|
// we disable the okButton while we search
|
||||||
@ -130,7 +124,11 @@ public class FindTextDialogFragment extends DialogFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SearchTask extends AsyncTask<Void, Void, Void>{
|
public interface SearchDialogInterface {
|
||||||
|
void onSearchDone(SearchResult searchResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SearchTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
LinkedList<Integer> foundIndex;
|
LinkedList<Integer> foundIndex;
|
||||||
boolean foundSomething;
|
boolean foundSomething;
|
||||||
@ -145,9 +143,9 @@ public class FindTextDialogFragment extends DialogFragment {
|
|||||||
Matcher matcher = null;
|
Matcher matcher = null;
|
||||||
foundSomething = false;
|
foundSomething = false;
|
||||||
|
|
||||||
if(isRegex) {
|
if (isRegex) {
|
||||||
try {
|
try {
|
||||||
if(caseSensitive)
|
if (caseSensitive)
|
||||||
matcher = Pattern.compile(whatToSearch, Pattern.MULTILINE).matcher(allText);
|
matcher = Pattern.compile(whatToSearch, Pattern.MULTILINE).matcher(allText);
|
||||||
else
|
else
|
||||||
matcher = Pattern.compile(whatToSearch, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE).matcher(allText);
|
matcher = Pattern.compile(whatToSearch, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE).matcher(allText);
|
||||||
@ -156,14 +154,14 @@ public class FindTextDialogFragment extends DialogFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isRegex) {
|
if (isRegex) {
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
foundSomething = true;
|
foundSomething = true;
|
||||||
|
|
||||||
foundIndex.add(matcher.start());
|
foundIndex.add(matcher.start());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(caseSensitive == false) { // by default is case sensitive
|
if (caseSensitive == false) { // by default is case sensitive
|
||||||
whatToSearch = whatToSearch.toLowerCase();
|
whatToSearch = whatToSearch.toLowerCase();
|
||||||
allText = allText.toLowerCase();
|
allText = allText.toLowerCase();
|
||||||
}
|
}
|
||||||
@ -183,15 +181,15 @@ public class FindTextDialogFragment extends DialogFragment {
|
|||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Void aVoid) {
|
protected void onPostExecute(Void aVoid) {
|
||||||
super.onPostExecute(aVoid);
|
super.onPostExecute(aVoid);
|
||||||
if(foundSomething) {
|
if (foundSomething) {
|
||||||
// the class that called this Dialog should implement the SearchDialogIterface
|
// the class that called this Dialog should implement the SearchDialogIterface
|
||||||
SearchDialogInterface searchDialogInterface;
|
SearchDialogInterface searchDialogInterface;
|
||||||
searchDialogInterface = ((SearchDialogInterface) getTargetFragment());
|
searchDialogInterface = ((SearchDialogInterface) getTargetFragment());
|
||||||
if(searchDialogInterface == null)
|
if (searchDialogInterface == null)
|
||||||
searchDialogInterface = ((SearchDialogInterface) getActivity());
|
searchDialogInterface = ((SearchDialogInterface) getActivity());
|
||||||
|
|
||||||
// if who called this has not implemented the interface we return nothing
|
// if who called this has not implemented the interface we return nothing
|
||||||
if(searchDialogInterface == null)
|
if (searchDialogInterface == null)
|
||||||
return;
|
return;
|
||||||
// else we return positions and other things
|
// else we return positions and other things
|
||||||
else {
|
else {
|
||||||
@ -203,11 +201,7 @@ public class FindTextDialogFragment extends DialogFragment {
|
|||||||
}
|
}
|
||||||
Toast.makeText(getActivity(), String.format(getString(R.string.occurrences_found), foundIndex.size()), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), String.format(getString(R.string.occurrences_found), foundIndex.size()), Toast.LENGTH_SHORT).show();
|
||||||
// dismiss the dialog
|
// dismiss the dialog
|
||||||
FindTextDialogFragment.this.dismiss();
|
FindTextDialog.this.dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface SearchDialogInterface {
|
|
||||||
void onSearchDone(SearchResult searchResult);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,206 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sharedcode.turboeditor.fragment;
|
|
||||||
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.ListView;
|
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
|
||||||
import sharedcode.turboeditor.adapter.AdapterDrawer;
|
|
||||||
import sharedcode.turboeditor.util.EventBusEvents;
|
|
||||||
import sharedcode.turboeditor.preferences.PreferenceHelper;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
|
||||||
|
|
||||||
|
|
||||||
public class NavigationDrawerListFragment extends Fragment implements AdapterView.OnItemClickListener, AdapterDrawer.Callbacks {
|
|
||||||
|
|
||||||
|
|
||||||
private AdapterDrawer arrayAdapter;
|
|
||||||
private ArrayList<File> files;
|
|
||||||
private ListView listView;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
|
||||||
// Our custom layout
|
|
||||||
View rootView = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
|
|
||||||
listView = (ListView) rootView.findViewById(android.R.id.list);
|
|
||||||
listView.setEmptyView(rootView.findViewById(android.R.id.empty));
|
|
||||||
files = new ArrayList<>();
|
|
||||||
arrayAdapter = new AdapterDrawer(getActivity(), files, this);
|
|
||||||
listView.setAdapter(arrayAdapter);
|
|
||||||
return rootView;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
|
||||||
super.onViewCreated(view, savedInstanceState);
|
|
||||||
listView.setOnItemClickListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
// Register the Event Bus for events
|
|
||||||
EventBus.getDefault().registerSticky(this);
|
|
||||||
// Refresh the list view
|
|
||||||
refreshList();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
// Unregister the Event Bus
|
|
||||||
EventBus.getDefault().unregister(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
|
||||||
// File paths saved in preferences
|
|
||||||
String[] savedPaths = PreferenceHelper.getSavedPaths(getActivity());
|
|
||||||
// Path of the file selected
|
|
||||||
String filePath = savedPaths[position];
|
|
||||||
// Send the event that a file was selected
|
|
||||||
EventBus.getDefault().post(new EventBusEvents.NewFileToOpen(new File(filePath)));
|
|
||||||
arrayAdapter.selectView(filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When a new file is opened
|
|
||||||
* Invoked by the main activity which receive the intent
|
|
||||||
*
|
|
||||||
* @param event The event called
|
|
||||||
*/
|
|
||||||
public void onEvent(EventBusEvents.NewFileToOpen event) {
|
|
||||||
|
|
||||||
// File paths saved in preferences
|
|
||||||
String[] savedPaths = PreferenceHelper.getSavedPaths(getActivity());
|
|
||||||
String selectedPath = event.getFile().getAbsolutePath();
|
|
||||||
for (String savedPath : savedPaths) {
|
|
||||||
// We don't need to save the file path twice
|
|
||||||
if (savedPath.equals(selectedPath)) {
|
|
||||||
arrayAdapter.selectView(selectedPath);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Add the path if it wasn't added before
|
|
||||||
addPath(selectedPath);
|
|
||||||
|
|
||||||
arrayAdapter.selectView(selectedPath);
|
|
||||||
|
|
||||||
EventBus.getDefault().removeStickyEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onEvent(EventBusEvents.SavedAFile event) {
|
|
||||||
if (addPath(event.getPath())) {
|
|
||||||
arrayAdapter.selectView(event.getPath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onEvent(EventBusEvents.ClosedAFile event) {
|
|
||||||
arrayAdapter.selectView("");
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean addPath(String path) {
|
|
||||||
// File paths saved in preferences
|
|
||||||
String[] savedPaths = PreferenceHelper.getSavedPaths(getActivity());
|
|
||||||
// StringBuilder
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
boolean pathAlreadyExist = false;
|
|
||||||
for (String savedPath : savedPaths) {
|
|
||||||
// Append the file path and a comma
|
|
||||||
sb.append(savedPath).append(",");
|
|
||||||
if (savedPath.equals(path))
|
|
||||||
pathAlreadyExist = true;
|
|
||||||
}
|
|
||||||
// Append new path
|
|
||||||
if (!pathAlreadyExist)
|
|
||||||
sb.append(path);
|
|
||||||
// Put the string and commit
|
|
||||||
PreferenceHelper.setSavedPaths(getActivity(), sb);
|
|
||||||
// Update list
|
|
||||||
refreshList();
|
|
||||||
|
|
||||||
return pathAlreadyExist == false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removePath(String path) {
|
|
||||||
// File paths saved in preferences
|
|
||||||
String[] savedPaths = PreferenceHelper.getSavedPaths(getActivity());
|
|
||||||
// StringBuilder
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
// for cycle
|
|
||||||
for (String savedPath : savedPaths) {
|
|
||||||
if (path.equals(savedPath)) continue;
|
|
||||||
sb.append(savedPath).append(",");
|
|
||||||
}
|
|
||||||
// Put the string and commit
|
|
||||||
PreferenceHelper.setSavedPaths(getActivity(), sb);
|
|
||||||
// Update list
|
|
||||||
refreshList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshList() {
|
|
||||||
// File paths saved in preferences
|
|
||||||
String[] savedPaths = PreferenceHelper.getSavedPaths(getActivity());
|
|
||||||
// File names for the list
|
|
||||||
files.clear();
|
|
||||||
// StringBuilder that will contain the file paths
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
// for cycle to convert paths to names
|
|
||||||
for (String path : savedPaths) {
|
|
||||||
File file = new File(path);
|
|
||||||
// Check that the file exist
|
|
||||||
if (file.exists()) {
|
|
||||||
files.add(file);
|
|
||||||
sb.append(path).append(",");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// save list without empty or non existed files
|
|
||||||
PreferenceHelper.setSavedPaths(getActivity(), sb);
|
|
||||||
// Set adapter
|
|
||||||
arrayAdapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void CancelItem(int position, boolean andCloseOpenedFile) {
|
|
||||||
String[] savedPaths = PreferenceHelper.getSavedPaths(getActivity());
|
|
||||||
removePath(savedPaths[position]);
|
|
||||||
if (andCloseOpenedFile)
|
|
||||||
EventBus.getDefault().post(new EventBusEvents.CannotOpenAFile());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void ItemSelected(String path) {
|
|
||||||
EventBus.getDefault().post(new EventBusEvents.AFileIsSelected(path));
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,28 +24,25 @@ import android.app.Dialog;
|
|||||||
import android.app.DialogFragment;
|
import android.app.DialogFragment;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.inputmethod.EditorInfo;
|
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
import sharedcode.turboeditor.R;
|
||||||
import sharedcode.turboeditor.activity.PreferenceAbout;
|
|
||||||
import sharedcode.turboeditor.preferences.PreferenceHelper;
|
import sharedcode.turboeditor.preferences.PreferenceHelper;
|
||||||
import sharedcode.turboeditor.util.SaveFileTask;
|
import sharedcode.turboeditor.task.SaveFileTask;
|
||||||
|
import sharedcode.turboeditor.views.DialogHelper;
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
public class NewFileDetailsDialogFragment extends DialogFragment {
|
public class NewFileDetailsDialog extends DialogFragment {
|
||||||
|
|
||||||
private EditText mName;
|
private EditText mName;
|
||||||
private EditText mFolder;
|
private EditText mFolder;
|
||||||
|
|
||||||
public static NewFileDetailsDialogFragment newInstance(String fileText, String fileEncoding) {
|
public static NewFileDetailsDialog newInstance(String fileText, String fileEncoding) {
|
||||||
final NewFileDetailsDialogFragment f = new NewFileDetailsDialogFragment();
|
final NewFileDetailsDialog f = new NewFileDetailsDialog();
|
||||||
final Bundle args = new Bundle();
|
final Bundle args = new Bundle();
|
||||||
args.putString("fileText", fileText);
|
args.putString("fileText", fileText);
|
||||||
args.putString("fileEncoding", fileEncoding);
|
args.putString("fileEncoding", fileEncoding);
|
||||||
@ -56,7 +53,11 @@ public class NewFileDetailsDialogFragment extends DialogFragment {
|
|||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
|
||||||
final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_fragment_new_file_details, null);
|
View view = new DialogHelper.Builder(getActivity())
|
||||||
|
.setTitle(R.string.file)
|
||||||
|
.setView(R.layout.dialog_fragment_new_file_details)
|
||||||
|
.createSkeletonView();
|
||||||
|
|
||||||
this.mName = (EditText) view.findViewById(android.R.id.text1);
|
this.mName = (EditText) view.findViewById(android.R.id.text1);
|
||||||
this.mFolder = (EditText) view.findViewById(android.R.id.text2);
|
this.mFolder = (EditText) view.findViewById(android.R.id.text2);
|
||||||
|
|
||||||
@ -72,9 +73,10 @@ public class NewFileDetailsDialogFragment extends DialogFragment {
|
|||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
if(!mName.getText().toString().isEmpty() && !mFolder.getText().toString().isEmpty()) {
|
if (!mName.getText().toString().isEmpty() && !mFolder.getText().toString().isEmpty()) {
|
||||||
File file = new File(mFolder.getText().toString(), mName.getText().toString());
|
File file = new File(mFolder.getText().toString(), mName.getText().toString());
|
||||||
new SaveFileTask(getActivity(), file.getPath(), getArguments().getString("fileText"), getArguments().getString("fileEncoding")).execute();
|
new SaveFileTask(getActivity(), file.getPath(), getArguments().getString("fileText"), getArguments().getString("fileEncoding")).execute();
|
||||||
|
PreferenceHelper.setWorkingFolder(getActivity(), file.getParent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,60 +24,89 @@ import android.app.Dialog;
|
|||||||
import android.app.DialogFragment;
|
import android.app.DialogFragment;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.view.View;
|
||||||
import sharedcode.turboeditor.R;
|
|
||||||
import sharedcode.turboeditor.preferences.SettingsFragment;
|
|
||||||
import sharedcode.turboeditor.util.SaveFileTask;
|
|
||||||
|
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class SaveFileDialogFragment extends DialogFragment {
|
import sharedcode.turboeditor.R;
|
||||||
|
import sharedcode.turboeditor.task.SaveFileTask;
|
||||||
|
import sharedcode.turboeditor.views.DialogHelper;
|
||||||
|
|
||||||
public static SaveFileDialogFragment newInstance(String filePath, String text) {
|
public class SaveFileDialog extends DialogFragment {
|
||||||
SaveFileDialogFragment frag = new SaveFileDialogFragment();
|
|
||||||
|
public static SaveFileDialog newInstance(String filePath, String text, String encoding) {
|
||||||
|
return newInstance(filePath, text, encoding, false, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SaveFileDialog newInstance(String filePath, String text, String encoding, boolean openNewFileAfter, String pathOfNewFile) {
|
||||||
|
SaveFileDialog frag = new SaveFileDialog();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString("filePath", filePath);
|
args.putString("filePath", filePath);
|
||||||
args.putString("text", text);
|
args.putString("text", text);
|
||||||
|
args.putString("encoding", encoding);
|
||||||
|
args.putBoolean("openNewFileAfter", openNewFileAfter);
|
||||||
|
args.putString("pathOfNewFile", pathOfNewFile);
|
||||||
frag.setArguments(args);
|
frag.setArguments(args);
|
||||||
return frag;
|
return frag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
final String filePath = getArguments().getString("filePath");
|
final String filePath = getArguments().getString("filePath");
|
||||||
final String text = getArguments().getString("text");
|
final String text = getArguments().getString("text");
|
||||||
|
final String encoding = getArguments().getString("encoding");
|
||||||
final String fileName = FilenameUtils.getName(filePath);
|
final String fileName = FilenameUtils.getName(filePath);
|
||||||
final File file = new File(filePath);
|
final File file = new File(filePath);
|
||||||
|
|
||||||
return new AlertDialog.Builder(getActivity())
|
View view = new DialogHelper.Builder(getActivity())
|
||||||
|
.setIcon(getResources().getDrawable(R.drawable.ic_action_save))
|
||||||
|
.setTitle(R.string.salva)
|
||||||
.setMessage(String.format(getString(R.string.save_changes), fileName))
|
.setMessage(String.format(getString(R.string.save_changes), fileName))
|
||||||
.setPositiveButton(android.R.string.yes,
|
.createCommonView();
|
||||||
|
|
||||||
|
return new AlertDialog.Builder(getActivity())
|
||||||
|
.setView(view)
|
||||||
|
.setPositiveButton(R.string.salva,
|
||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
if(!fileName.isEmpty())
|
if (!fileName.isEmpty())
|
||||||
new SaveFileTask(getActivity(), filePath, text, SettingsFragment.sCurrentEncoding).execute();
|
new SaveFileTask(getActivity(), filePath, text,
|
||||||
|
encoding).execute();
|
||||||
else {
|
else {
|
||||||
NewFileDetailsDialogFragment dialogFrag = NewFileDetailsDialogFragment.newInstance(text, SettingsFragment.sCurrentEncoding);
|
NewFileDetailsDialog dialogFrag =
|
||||||
dialogFrag.show(getFragmentManager().beginTransaction(), "dialog");
|
NewFileDetailsDialog.newInstance(text,
|
||||||
|
encoding);
|
||||||
|
dialogFrag.show(getFragmentManager().beginTransaction(),
|
||||||
|
"dialog");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.setNegativeButton(android.R.string.no,
|
.setNeutralButton(android.R.string.cancel, null)
|
||||||
|
.setNegativeButton(R.string.no,
|
||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
ISaveDialog target = (ISaveDialog) getTargetFragment();
|
||||||
|
if (target == null) {
|
||||||
|
target = (ISaveDialog) getActivity();
|
||||||
|
}
|
||||||
|
target.userDoesntWantToSave(
|
||||||
|
getArguments().getBoolean("openNewFileAfter"),
|
||||||
|
getArguments().getString("pathOfNewFile")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.create();
|
.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum Action {
|
public interface ISaveDialog {
|
||||||
SaveAFile
|
void userDoesntWantToSave(boolean openNewFile, String pathOfNewFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -28,18 +28,19 @@ import android.view.View;
|
|||||||
import android.widget.NumberPicker;
|
import android.widget.NumberPicker;
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
import sharedcode.turboeditor.R;
|
||||||
|
import sharedcode.turboeditor.views.DialogHelper;
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
public class SeekbarDialogFragment extends DialogFragment {
|
public class SeekbarDialog extends DialogFragment {
|
||||||
|
|
||||||
private NumberPicker mSeekBar;
|
private NumberPicker mSeekBar;
|
||||||
|
|
||||||
public static SeekbarDialogFragment newInstance(final Actions action) {
|
public static SeekbarDialog newInstance(final Actions action) {
|
||||||
return SeekbarDialogFragment.newInstance(action, 0, 50, 100);
|
return SeekbarDialog.newInstance(action, 0, 50, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SeekbarDialogFragment newInstance(final Actions action, final int min, final int current, final int max) {
|
public static SeekbarDialog newInstance(final Actions action, final int min, final int current, final int max) {
|
||||||
final SeekbarDialogFragment f = new SeekbarDialogFragment();
|
final SeekbarDialog f = new SeekbarDialog();
|
||||||
final Bundle args = new Bundle();
|
final Bundle args = new Bundle();
|
||||||
args.putSerializable("action", action);
|
args.putSerializable("action", action);
|
||||||
args.putInt("min", min);
|
args.putInt("min", min);
|
||||||
@ -52,9 +53,28 @@ public class SeekbarDialogFragment extends DialogFragment {
|
|||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
|
||||||
final Actions action = (Actions) getArguments().getSerializable("action");
|
Actions action = (Actions) getArguments().getSerializable("action");
|
||||||
|
int title;
|
||||||
|
switch (action){
|
||||||
|
case FontSize:
|
||||||
|
title = R.string.font_size;
|
||||||
|
break;
|
||||||
|
case SelectPage:
|
||||||
|
title = R.string.goto_page;
|
||||||
|
break;
|
||||||
|
case GoToLine:
|
||||||
|
title = R.string.goto_line;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
title = R.string.nome_app_turbo_editor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
View view = new DialogHelper.Builder(getActivity())
|
||||||
|
.setTitle(title)
|
||||||
|
.setView(R.layout.dialog_fragment_seekbar)
|
||||||
|
.createSkeletonView();
|
||||||
|
|
||||||
final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_fragment_seekbar, null);
|
|
||||||
this.mSeekBar = (NumberPicker) view.findViewById(android.R.id.input);
|
this.mSeekBar = (NumberPicker) view.findViewById(android.R.id.input);
|
||||||
this.mSeekBar.setMaxValue(getArguments().getInt("max"));
|
this.mSeekBar.setMaxValue(getArguments().getInt("max"));
|
||||||
this.mSeekBar.setMinValue(getArguments().getInt("min"));
|
this.mSeekBar.setMinValue(getArguments().getInt("min"));
|
||||||
@ -82,9 +102,9 @@ public class SeekbarDialogFragment extends DialogFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void returnData() {
|
void returnData() {
|
||||||
onSeekbarDialogDismissed target = (onSeekbarDialogDismissed) getTargetFragment();
|
ISeekbarDialog target = (ISeekbarDialog) getTargetFragment();
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
target = (onSeekbarDialogDismissed) getActivity();
|
target = (ISeekbarDialog) getActivity();
|
||||||
}
|
}
|
||||||
target.onSeekbarDialogDismissed(
|
target.onSeekbarDialogDismissed(
|
||||||
(Actions) getArguments().getSerializable("action"),
|
(Actions) getArguments().getSerializable("action"),
|
||||||
@ -94,10 +114,10 @@ public class SeekbarDialogFragment extends DialogFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum Actions {
|
public enum Actions {
|
||||||
FileSize, SelectPage, GoToLine
|
FontSize, SelectPage, GoToLine
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface onSeekbarDialogDismissed {
|
public interface ISeekbarDialog {
|
||||||
void onSeekbarDialogDismissed(Actions action, int value);
|
void onSeekbarDialogDismissed(Actions action, int value);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<Donation> {
|
||||||
|
|
||||||
|
private final HashSet<String> mInventorySet;
|
||||||
|
private final LayoutInflater mInflater;
|
||||||
|
private final String mDonationAmountLabel;
|
||||||
|
|
||||||
|
private final int mColorNormal;
|
||||||
|
private final int mColorPurchased;
|
||||||
|
|
||||||
|
public DonationAdapter(Context context, Donation[] items, HashSet<String> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,370 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<String> 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.<br/>
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <b>Make sure you call {@link #disposeBilling()}!</b>
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,582 @@
|
|||||||
|
// 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:
|
||||||
|
* <p>
|
||||||
|
* 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
|
||||||
|
* <a href="http://iharder.net/xmlizable">http://iharder.net/xmlizable</a>
|
||||||
|
* periodically to check for updates or to contribute improvements.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
* <p/>
|
||||||
|
* <p>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 <var>source</var>
|
||||||
|
* and writes the resulting four Base64 bytes to <var>destination</var>.
|
||||||
|
* The source and destination arrays can be manipulated
|
||||||
|
* anywhere along their length by specifying
|
||||||
|
* <var>srcOffset</var> and <var>destOffset</var>.
|
||||||
|
* This method does not check to make sure your arrays
|
||||||
|
* are large enough to accommodate <var>srcOffset</var> + 3 for
|
||||||
|
* the <var>source</var> array or <var>destOffset</var> + 4 for
|
||||||
|
* the <var>destination</var> array.
|
||||||
|
* The actual number of significant bytes in your array is
|
||||||
|
* given by <var>numSigBytes</var>.
|
||||||
|
*
|
||||||
|
* @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 <var>destination</var> 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 <var>source</var>
|
||||||
|
* and writes the resulting bytes (up to three of them)
|
||||||
|
* to <var>destination</var>.
|
||||||
|
* The source and destination arrays can be manipulated
|
||||||
|
* anywhere along their length by specifying
|
||||||
|
* <var>srcOffset</var> and <var>destOffset</var>.
|
||||||
|
* This method does not check to make sure your arrays
|
||||||
|
* are large enough to accommodate <var>srcOffset</var> + 4 for
|
||||||
|
* the <var>source</var> array or <var>destOffset</var> + 3 for
|
||||||
|
* the <var>destination</var> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -17,21 +17,21 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sharedcode.turboeditor.fragment;
|
package sharedcode.turboeditor.iab.utils;
|
||||||
|
|
||||||
import android.app.Fragment;
|
/**
|
||||||
import android.os.Bundle;
|
* Exception thrown when encountering an invalid Base64 input character.
|
||||||
import android.view.LayoutInflater;
|
*
|
||||||
import android.view.View;
|
* @author nelson
|
||||||
import android.view.ViewGroup;
|
*/
|
||||||
|
public class Base64DecoderException extends Exception {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
public Base64DecoderException() {
|
||||||
|
super();
|
||||||
public class NoFileOpenedFragment extends Fragment {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
|
||||||
return inflater.inflate(R.layout.fragment_no_file_open, container, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Base64DecoderException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,966 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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.
|
||||||
|
* <p/>
|
||||||
|
* 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.
|
||||||
|
* <p/>
|
||||||
|
* 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.
|
||||||
|
* <p/>
|
||||||
|
* 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.
|
||||||
|
* <p/>
|
||||||
|
* 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<ResolveInfo> 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<String> 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<String> moreItemSkus,
|
||||||
|
List<String> 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<String> 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<Purchase> 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<Purchase> 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<String> ownedSkus = ownedItems.getStringArrayList(
|
||||||
|
RESPONSE_INAPP_ITEM_LIST);
|
||||||
|
ArrayList<String> purchaseDataList = ownedItems.getStringArrayList(
|
||||||
|
RESPONSE_INAPP_PURCHASE_DATA_LIST);
|
||||||
|
ArrayList<String> 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<String> moreSkus)
|
||||||
|
throws RemoteException, JSONException {
|
||||||
|
logDebug("Querying SKU details.");
|
||||||
|
ArrayList<String> 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<String> 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<Purchase> purchases,
|
||||||
|
final OnConsumeFinishedListener singleListener,
|
||||||
|
final OnConsumeMultiFinishedListener multiListener) {
|
||||||
|
final Handler handler = new Handler();
|
||||||
|
flagStartAsync("consume");
|
||||||
|
(new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
final List<IabResult> 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<Purchase> purchases, List<IabResult> results);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<String, SkuDetails> mSkuMap = new HashMap<>();
|
||||||
|
Map<String, Purchase> 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<String> getAllOwnedSkus() {
|
||||||
|
return new ArrayList<>(mPurchaseMap.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all owned product IDs of a given type
|
||||||
|
*/
|
||||||
|
List<String> getAllOwnedSkus(String itemType) {
|
||||||
|
List<String> 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<Purchase> getAllPurchases() {
|
||||||
|
return new ArrayList<>(mPurchaseMap.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
void addSkuDetails(SkuDetails d) {
|
||||||
|
mSkuMap.put(d.getSku(), d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addPurchase(Purchase p) {
|
||||||
|
mPurchaseMap.put(p.getSku(), p);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -49,7 +49,7 @@ public final class PreferenceHelper {
|
|||||||
return getPrefs(context).getBoolean("editor_line_numbers", true);
|
return getPrefs(context).getBoolean("editor_line_numbers", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean getSyntaxHiglight(Context context) {
|
public static boolean getSyntaxHighlight(Context context) {
|
||||||
return getPrefs(context).getBoolean("editor_syntax_highlight", false);
|
return getPrefs(context).getBoolean("editor_syntax_highlight", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,10 +73,6 @@ public final class PreferenceHelper {
|
|||||||
return getPrefs(context).getBoolean("send_error_reports", true);
|
return getPrefs(context).getBoolean("send_error_reports", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getLastDayAdShowed(Context context) {
|
|
||||||
return getPrefs(context).getInt("last_day_ad_showed", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getEncoding(Context context) {
|
public static String getEncoding(Context context) {
|
||||||
return getPrefs(context).getString("editor_encoding", "UTF-8");
|
return getPrefs(context).getString("editor_encoding", "UTF-8");
|
||||||
}
|
}
|
||||||
@ -105,6 +101,17 @@ public final class PreferenceHelper {
|
|||||||
return getPrefs(context).getBoolean("read_only", false);
|
return getPrefs(context).getBoolean("read_only", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean getIgnoreBackButton(Context context) {
|
||||||
|
return getPrefs(context).getBoolean("ignore_back_button", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean getSplitText(Context context) {
|
||||||
|
return getPrefs(context).getBoolean("page_system_active", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasDonated(Context context) {
|
||||||
|
return getPrefs(context).getBoolean("has_donated", false);
|
||||||
|
}
|
||||||
// Setter methods
|
// Setter methods
|
||||||
|
|
||||||
public static void setUseMonospace(Context context, boolean value) {
|
public static void setUseMonospace(Context context, boolean value) {
|
||||||
@ -115,7 +122,7 @@ public final class PreferenceHelper {
|
|||||||
getEditor(context).putBoolean("editor_line_numbers", value).commit();
|
getEditor(context).putBoolean("editor_line_numbers", value).commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setSyntaxHiglight(Context context, boolean value) {
|
public static void setSyntaxHighlight(Context context, boolean value) {
|
||||||
getEditor(context).putBoolean("editor_syntax_highlight", value).commit();
|
getEditor(context).putBoolean("editor_syntax_highlight", value).commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,30 +130,10 @@ public final class PreferenceHelper {
|
|||||||
getEditor(context).putBoolean("editor_wrap_content", value).commit();
|
getEditor(context).putBoolean("editor_wrap_content", value).commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setLightTheme(Context context, boolean value) {
|
|
||||||
getEditor(context).putBoolean("light_theme", value).commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setSuggestionActive(Context context, boolean value) {
|
|
||||||
getEditor(context).putBoolean("suggestion_active", value).commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setAutoencoding(Context context, boolean value) {
|
public static void setAutoencoding(Context context, boolean value) {
|
||||||
getEditor(context).putBoolean("autoencoding", value).commit();
|
getEditor(context).putBoolean("autoencoding", value).commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setSendErrorReports(Context context, boolean value) {
|
|
||||||
getEditor(context).putBoolean("send_error_reports", value).commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setLastDayAdShowed(Context context, int value) {
|
|
||||||
getEditor(context).putInt("last_day_ad_showed", value).commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setEncoding(Context context, String value) {
|
|
||||||
getEditor(context).putString("editor_encoding", value).commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setFontSize(Context context, int value) {
|
public static void setFontSize(Context context, int value) {
|
||||||
getEditor(context).putInt("font_size", value).commit();
|
getEditor(context).putInt("font_size", value).commit();
|
||||||
}
|
}
|
||||||
@ -163,12 +150,39 @@ public final class PreferenceHelper {
|
|||||||
getEditor(context).putBoolean("page_system_button_popup_shown", value).commit();
|
getEditor(context).putBoolean("page_system_button_popup_shown", value).commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setAutoSave(Context context, boolean value) {
|
|
||||||
getEditor(context).putBoolean("auto_save", value).commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setReadOnly(Context context, boolean value) {
|
public static void setReadOnly(Context context, boolean value) {
|
||||||
getEditor(context).putBoolean("read_only", value).commit();
|
getEditor(context).putBoolean("read_only", value).commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setHasDonated(Context context, boolean value) {
|
||||||
|
getEditor(context).putBoolean("has_donated", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setLightTheme(Context context, boolean value) {
|
||||||
|
getEditor(context).putBoolean("light_theme", value).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSuggestionsActive(Context context, boolean value) {
|
||||||
|
getEditor(context).putBoolean("suggestion_active", value).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setAutoSave(Context context, boolean value) {
|
||||||
|
getEditor(context).putBoolean("auto_save", value).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setIgnoreBackButton(Context context, boolean value) {
|
||||||
|
getEditor(context).putBoolean("ignore_back_button", value).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSplitText(Context context, boolean value) {
|
||||||
|
getEditor(context).putBoolean("page_system_active", value).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendErrorReport(Context context, boolean value) {
|
||||||
|
getEditor(context).putBoolean("ignore_back_button", value).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setEncoding(Context context, String value) {
|
||||||
|
getEditor(context).putString("editor_encoding", value).commit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,27 +20,23 @@
|
|||||||
package sharedcode.turboeditor.preferences;
|
package sharedcode.turboeditor.preferences;
|
||||||
|
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.widget.SwitchCompat;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.CheckBox;
|
|
||||||
import android.widget.CheckedTextView;
|
|
||||||
import android.widget.CompoundButton;
|
import android.widget.CompoundButton;
|
||||||
import android.widget.Switch;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
|
||||||
import sharedcode.turboeditor.fragment.EncodingDialogFragment;
|
|
||||||
import sharedcode.turboeditor.fragment.SeekbarDialogFragment;
|
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
import de.greenrobot.event.EventBus;
|
||||||
|
import sharedcode.turboeditor.R;
|
||||||
|
import sharedcode.turboeditor.fragment.EncodingDialog;
|
||||||
|
import sharedcode.turboeditor.fragment.SeekbarDialog;
|
||||||
import sharedcode.turboeditor.util.ProCheckUtils;
|
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;
|
||||||
import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.AUTO_SAVE;
|
|
||||||
import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.ENCODING;
|
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.FONT_SIZE;
|
||||||
import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.LINE_NUMERS;
|
import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.LINE_NUMERS;
|
||||||
@ -51,97 +47,109 @@ import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChan
|
|||||||
import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.THEME_CHANGE;
|
import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.THEME_CHANGE;
|
||||||
import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.WRAP_CONTENT;
|
import static sharedcode.turboeditor.util.EventBusEvents.APreferenceValueWasChanged.Type.WRAP_CONTENT;
|
||||||
|
|
||||||
public class SettingsFragment extends Fragment implements EncodingDialogFragment.DialogListener, SeekbarDialogFragment.onSeekbarDialogDismissed {
|
public class SettingsFragment extends Fragment implements SeekbarDialog.ISeekbarDialog, EncodingDialog.DialogListener {
|
||||||
|
|
||||||
public static String sCurrentEncoding;
|
|
||||||
// Editor Variables
|
// Editor Variables
|
||||||
public static boolean sLineNumbers;
|
private boolean sLineNumbers;
|
||||||
public static boolean sColorSyntax;
|
private boolean sColorSyntax;
|
||||||
public static boolean sWrapContent;
|
private boolean sWrapContent;
|
||||||
public static int sFontSize;
|
private boolean sUseMonospace;
|
||||||
public static boolean sUseMonospace;
|
private boolean sReadOnly;
|
||||||
public static boolean sLightTheme;
|
|
||||||
public static boolean sSuggestionsActive;
|
private boolean sLightTheme;
|
||||||
public static boolean sAutoSave;
|
private boolean sSuggestions;
|
||||||
public static boolean sReadOnly;
|
private boolean sAutoSave;
|
||||||
public static boolean sSendErrorReports;
|
private boolean sIgnoreBackButton;
|
||||||
|
private boolean sSplitText;
|
||||||
|
private boolean sErrorReports;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
SettingsFragment.sCurrentEncoding = PreferenceHelper.getEncoding(getActivity());
|
sUseMonospace = PreferenceHelper.getUseMonospace(getActivity());
|
||||||
SettingsFragment.sUseMonospace = PreferenceHelper.getUseMonospace(getActivity());
|
sColorSyntax = PreferenceHelper.getSyntaxHighlight(getActivity());
|
||||||
SettingsFragment.sColorSyntax = PreferenceHelper.getSyntaxHiglight(getActivity());
|
sWrapContent = PreferenceHelper.getWrapContent(getActivity());
|
||||||
SettingsFragment.sWrapContent = PreferenceHelper.getWrapContent(getActivity());
|
sLineNumbers = PreferenceHelper.getLineNumbers(getActivity());
|
||||||
SettingsFragment.sLineNumbers = PreferenceHelper.getLineNumbers(getActivity());
|
sReadOnly = PreferenceHelper.getReadOnly(getActivity());
|
||||||
SettingsFragment.sFontSize = PreferenceHelper.getFontSize(getActivity());
|
|
||||||
SettingsFragment.sSuggestionsActive = PreferenceHelper.getSuggestionActive(getActivity());
|
sLightTheme = PreferenceHelper.getLightTheme(getActivity());
|
||||||
SettingsFragment.sLightTheme = PreferenceHelper.getLightTheme(getActivity());
|
sSuggestions = PreferenceHelper.getSuggestionActive(getActivity());
|
||||||
SettingsFragment.sAutoSave = PreferenceHelper.getAutoSave(getActivity());
|
sAutoSave = PreferenceHelper.getAutoSave(getActivity());
|
||||||
SettingsFragment.sReadOnly = PreferenceHelper.getReadOnly(getActivity());
|
sIgnoreBackButton = PreferenceHelper.getIgnoreBackButton(getActivity());
|
||||||
SettingsFragment.sSendErrorReports = PreferenceHelper.getReadOnly(getActivity());
|
sSplitText = PreferenceHelper.getSplitText(getActivity());
|
||||||
|
sErrorReports = PreferenceHelper.getSendErrorReports(getActivity());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
// Our custom layout
|
// Our custom layout
|
||||||
View rootView = inflater.inflate(R.layout.fragment_settings, container, false);
|
final View rootView = inflater.inflate(R.layout.fragment_settings, container, false);
|
||||||
final CheckBox switchLineNumbers, switchSyntax, switchWrapContent, switchMonospace, switchLightTheme, switchSuggestionsActive, switchAutoSave, switchReadOnly, switchSendErrorReports;
|
final SwitchCompat swLineNumbers, swSyntax, swWrapContent, swMonospace, swReadOnly;
|
||||||
switchLineNumbers = (CheckBox) rootView.findViewById(R.id.switch_line_numbers);
|
final SwitchCompat swLightTheme, swSuggestions, swAutoSave, swIgnoreBackButton, swSplitText, swErrorReports;
|
||||||
switchSyntax = (CheckBox) rootView.findViewById(R.id.switch_syntax);
|
|
||||||
switchWrapContent = (CheckBox) rootView.findViewById(R.id.switch_wrap_content);
|
swLineNumbers = (SwitchCompat) rootView.findViewById(R.id.switch_line_numbers);
|
||||||
switchMonospace = (CheckBox) rootView.findViewById(R.id.switch_monospace);
|
swSyntax = (SwitchCompat) rootView.findViewById(R.id.switch_syntax);
|
||||||
switchLightTheme = (CheckBox) rootView.findViewById(R.id.switch_light_theme);
|
swWrapContent = (SwitchCompat) rootView.findViewById(R.id.switch_wrap_content);
|
||||||
switchSuggestionsActive = (CheckBox) rootView.findViewById(R.id.switch_suggestions_active);
|
swMonospace = (SwitchCompat) rootView.findViewById(R.id.switch_monospace);
|
||||||
switchAutoSave = (CheckBox) rootView.findViewById(R.id.switch_auto_save);
|
swReadOnly = (SwitchCompat) rootView.findViewById(R.id.switch_read_only);
|
||||||
switchReadOnly = (CheckBox) rootView.findViewById(R.id.switch_read_only);
|
|
||||||
switchSendErrorReports = (CheckBox) rootView.findViewById(R.id.switch_send_error_reports);
|
|
||||||
|
|
||||||
switchLineNumbers.setChecked(sLineNumbers);
|
swLightTheme = (SwitchCompat) rootView.findViewById(R.id.switch_light_theme);
|
||||||
switchSyntax.setChecked(sColorSyntax);
|
swSuggestions = (SwitchCompat) rootView.findViewById(R.id.switch_suggestions_active);
|
||||||
switchWrapContent.setChecked(sWrapContent);
|
swAutoSave = (SwitchCompat) rootView.findViewById(R.id.switch_auto_save);
|
||||||
switchMonospace.setChecked(sUseMonospace);
|
swIgnoreBackButton = (SwitchCompat) rootView.findViewById(R.id.switch_ignore_backbutton);
|
||||||
switchLightTheme.setChecked(sLightTheme);
|
swSplitText = (SwitchCompat) rootView.findViewById(R.id.switch_page_system);
|
||||||
switchSuggestionsActive.setChecked(sSuggestionsActive);
|
swErrorReports = (SwitchCompat) rootView.findViewById(R.id.switch_send_error_reports);
|
||||||
switchAutoSave.setChecked(sAutoSave);
|
|
||||||
switchReadOnly.setChecked(sReadOnly);
|
|
||||||
|
|
||||||
|
swLineNumbers.setChecked(sLineNumbers);
|
||||||
|
swSyntax.setChecked(sColorSyntax);
|
||||||
|
swWrapContent.setChecked(sWrapContent);
|
||||||
|
swMonospace.setChecked(sUseMonospace);
|
||||||
|
swReadOnly.setChecked(sReadOnly);
|
||||||
|
|
||||||
TextView encodingView, fontSizeView, goProView;
|
swLightTheme.setChecked(sLightTheme);
|
||||||
encodingView = (TextView) rootView.findViewById(R.id.drawer_button_encoding);
|
swSuggestions.setChecked(sSuggestions);
|
||||||
|
swAutoSave.setChecked(sAutoSave);
|
||||||
|
swIgnoreBackButton.setChecked(sIgnoreBackButton);
|
||||||
|
swSplitText.setChecked(sSplitText);
|
||||||
|
swErrorReports.setChecked(sErrorReports);
|
||||||
|
|
||||||
|
TextView fontSizeView, encodingView, donateView, extraOptionsView;
|
||||||
fontSizeView = (TextView) rootView.findViewById(R.id.drawer_button_font_size);
|
fontSizeView = (TextView) rootView.findViewById(R.id.drawer_button_font_size);
|
||||||
goProView = (TextView) rootView.findViewById(R.id.drawer_button_go_pro);
|
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);
|
||||||
|
|
||||||
switchLineNumbers.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
if(ProCheckUtils.isPro(getActivity(), false))
|
||||||
|
ViewUtils.setVisible(donateView, false);
|
||||||
|
|
||||||
|
swLineNumbers.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
sLineNumbers = isChecked;
|
|
||||||
PreferenceHelper.setLineNumbers(getActivity(), isChecked);
|
PreferenceHelper.setLineNumbers(getActivity(), isChecked);
|
||||||
EventBus.getDefault().post(new APreferenceValueWasChanged(LINE_NUMERS));
|
EventBus.getDefault().post(new APreferenceValueWasChanged(LINE_NUMERS));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
switchSyntax.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
swSyntax.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
sColorSyntax = isChecked;
|
sColorSyntax = isChecked;
|
||||||
PreferenceHelper.setSyntaxHiglight(getActivity(), isChecked);
|
PreferenceHelper.setSyntaxHighlight(getActivity(), isChecked);
|
||||||
EventBus.getDefault().post(new APreferenceValueWasChanged(SYNTAX));
|
EventBus.getDefault().post(new APreferenceValueWasChanged(SYNTAX));
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
switchWrapContent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
swWrapContent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
sWrapContent = isChecked;
|
|
||||||
PreferenceHelper.setWrapContent(getActivity(), isChecked);
|
PreferenceHelper.setWrapContent(getActivity(), isChecked);
|
||||||
EventBus.getDefault().post(new APreferenceValueWasChanged(WRAP_CONTENT));
|
EventBus.getDefault().post(new APreferenceValueWasChanged(WRAP_CONTENT));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
switchMonospace.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
swMonospace.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
sUseMonospace = isChecked;
|
sUseMonospace = isChecked;
|
||||||
@ -151,59 +159,14 @@ public class SettingsFragment extends Fragment implements EncodingDialogFragment
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
switchLightTheme.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
swReadOnly.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
sLightTheme = isChecked;
|
|
||||||
PreferenceHelper.setLightTheme(getActivity(), isChecked);
|
|
||||||
EventBus.getDefault().post(new APreferenceValueWasChanged(THEME_CHANGE));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
switchSuggestionsActive.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
|
||||||
sSuggestionsActive = isChecked;
|
|
||||||
PreferenceHelper.setSuggestionActive(getActivity(), isChecked);
|
|
||||||
EventBus.getDefault().post(new APreferenceValueWasChanged(TEXT_SUGGESTIONS));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
switchAutoSave.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
|
||||||
sAutoSave = isChecked;
|
|
||||||
PreferenceHelper.setAutoSave(getActivity(), isChecked);
|
|
||||||
EventBus.getDefault().post(new APreferenceValueWasChanged(AUTO_SAVE));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
switchReadOnly.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
|
||||||
sReadOnly = isChecked;
|
|
||||||
PreferenceHelper.setReadOnly(getActivity(), isChecked);
|
PreferenceHelper.setReadOnly(getActivity(), isChecked);
|
||||||
EventBus.getDefault().post(new APreferenceValueWasChanged(READ_ONLY));
|
EventBus.getDefault().post(new APreferenceValueWasChanged(READ_ONLY));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
switchSendErrorReports.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
|
||||||
sSendErrorReports = isChecked;
|
|
||||||
PreferenceHelper.setSendErrorReports(getActivity(), isChecked);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
encodingView.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
EncodingDialogFragment dialogFrag = EncodingDialogFragment.newInstance();
|
|
||||||
dialogFrag.setTargetFragment(SettingsFragment.this, 0);
|
|
||||||
dialogFrag.show(getFragmentManager().beginTransaction(), "dialog");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
fontSizeView.setOnClickListener(new View.OnClickListener() {
|
fontSizeView.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
@ -211,54 +174,67 @@ public class SettingsFragment extends Fragment implements EncodingDialogFragment
|
|||||||
int fontCurrent = //(int) (mEditor.getTextSize() / scaledDensity);
|
int fontCurrent = //(int) (mEditor.getTextSize() / scaledDensity);
|
||||||
//fontMax / 2;
|
//fontMax / 2;
|
||||||
PreferenceHelper.getFontSize(getActivity());
|
PreferenceHelper.getFontSize(getActivity());
|
||||||
SeekbarDialogFragment dialogFrag = SeekbarDialogFragment.newInstance(SeekbarDialogFragment.Actions.FileSize, 1, fontCurrent, fontMax);
|
SeekbarDialog dialogFrag = SeekbarDialog.newInstance(SeekbarDialog.Actions
|
||||||
|
.FontSize, 1, fontCurrent, fontMax);
|
||||||
dialogFrag.setTargetFragment(SettingsFragment.this, 0);
|
dialogFrag.setTargetFragment(SettingsFragment.this, 0);
|
||||||
dialogFrag.show(getFragmentManager().beginTransaction(), "dialog");
|
dialogFrag.show(getFragmentManager().beginTransaction(), "dialog");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
goProView.setOnClickListener(new View.OnClickListener() {
|
encodingView.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
try {
|
EncodingDialog dialogFrag = EncodingDialog.newInstance();
|
||||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.maskyn.fileeditorpro"))
|
dialogFrag.setTargetFragment(SettingsFragment.this, 0);
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
dialogFrag.show(getFragmentManager().beginTransaction(), "dialog");
|
||||||
} catch (Exception e) {
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
|
extraOptionsView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
View otherOptions = rootView.findViewById(R.id.other_options);
|
||||||
|
boolean isVisible = otherOptions.getVisibility() == View.VISIBLE;
|
||||||
|
ViewUtils.setVisible(otherOptions, !isVisible);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
|
EventBus.getDefault().post(new APreferenceValueWasChanged(THEME_CHANGE));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
swSuggestions.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
|
PreferenceHelper.setSuggestionsActive(getActivity(), isChecked);
|
||||||
|
EventBus.getDefault().post(new APreferenceValueWasChanged(TEXT_SUGGESTIONS));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
goProView.setVisibility(ProCheckUtils.isPro(getActivity()) ? View.GONE : View.VISIBLE);
|
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEncodingSelected(String value) {
|
public void onSeekbarDialogDismissed(SeekbarDialog.Actions action, int value) {
|
||||||
PreferenceHelper.setEncoding(getActivity(), value);
|
|
||||||
EventBus.getDefault().post(new APreferenceValueWasChanged(ENCODING));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSeekbarDialogDismissed(SeekbarDialogFragment.Actions action, int value) {
|
|
||||||
sFontSize = value;
|
|
||||||
PreferenceHelper.setFontSize(getActivity(), value);
|
PreferenceHelper.setFontSize(getActivity(), value);
|
||||||
EventBus.getDefault().post(new APreferenceValueWasChanged(FONT_SIZE));
|
EventBus.getDefault().post(new APreferenceValueWasChanged(FONT_SIZE));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* This interface must be implemented by activities that contain this
|
public void onEncodingSelected(String result) {
|
||||||
* fragment to allow an interaction in this fragment to be communicated
|
PreferenceHelper.setEncoding(getActivity(), result);
|
||||||
* to the activity and potentially other fragments contained in that
|
EventBus.getDefault().post(new APreferenceValueWasChanged(ENCODING));
|
||||||
* activity.
|
|
||||||
* <p/>
|
|
||||||
* See the Android Training lesson <a href=
|
|
||||||
* "http://developer.android.com/training/basics/fragments/communicating.html"
|
|
||||||
* >Communicating with Other Fragments</a> for more information.
|
|
||||||
*/
|
|
||||||
public interface OnFragmentInteractionListener {
|
|
||||||
// TODO: Update argument type and name
|
|
||||||
public void onFragmentInteraction(Uri uri);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sharedcode.turboeditor.root;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class LinuxShell {
|
||||||
|
|
||||||
|
private static final String UNIX_ESCAPE_EXPRESSION = "(\\(|\\)|\\[|\\]|\\s|\'|\"|`|\\{|\\}|&|\\\\|\\?)";
|
||||||
|
|
||||||
|
public static String getCommandLineString(String input) {
|
||||||
|
return input.replaceAll(UNIX_ESCAPE_EXPRESSION, "\\\\$1");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BufferedReader execute(String cmd) {
|
||||||
|
BufferedReader reader = null;
|
||||||
|
try {
|
||||||
|
Process process = Runtime.getRuntime().exec("su");
|
||||||
|
DataOutputStream os = new DataOutputStream(
|
||||||
|
process.getOutputStream());
|
||||||
|
os.writeBytes(cmd + "\n");
|
||||||
|
os.writeBytes("exit\n");
|
||||||
|
reader = new BufferedReader(new InputStreamReader(
|
||||||
|
process.getInputStream()));
|
||||||
|
String err = (new BufferedReader(new InputStreamReader(
|
||||||
|
process.getErrorStream()))).readLine();
|
||||||
|
os.flush();
|
||||||
|
|
||||||
|
if (process.waitFor() != 0 || (!"".equals(err) && null != err)
|
||||||
|
&& containsIllegals(err) != true) {
|
||||||
|
Log.e("Root Error, cmd: " + cmd, err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return reader;
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean containsIllegals(String toExamine) {
|
||||||
|
// checks for "+" sign so the program doesn't throw an error when its
|
||||||
|
// not erroring.
|
||||||
|
Pattern pattern = Pattern.compile("[+]");
|
||||||
|
Matcher matcher = pattern.matcher(toExamine);
|
||||||
|
return matcher.find();
|
||||||
|
}
|
||||||
|
}
|
@ -32,7 +32,7 @@
|
|||||||
* along with 920 Text Editor. If not, see <http://www.gnu.org/licenses/>.
|
* along with 920 Text Editor. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sharedcode.turboeditor.util;
|
package sharedcode.turboeditor.root;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
@ -80,8 +80,7 @@ public class RootUtils {
|
|||||||
} else {
|
} else {
|
||||||
BufferedReader reader = null; //errReader = null;
|
BufferedReader reader = null; //errReader = null;
|
||||||
try {
|
try {
|
||||||
|
LinuxShell.execute("ls -a " + LinuxShell.getCommandLineString(path));
|
||||||
reader = LinuxShell.execute("IFS='\n';CURDIR='" + LinuxShell.getCmdPath(path) + "';for i in `ls $CURDIR`; do if [ -d $CURDIR/$i ]; then echo \"d $CURDIR/$i\";else echo \"f $CURDIR/$i\"; fi; done");
|
|
||||||
if (reader == null)
|
if (reader == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -17,14 +17,12 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sharedcode.turboeditor.util;
|
package sharedcode.turboeditor.task;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
|
||||||
|
|
||||||
import org.sufficientlysecure.rootcommands.Shell;
|
import org.sufficientlysecure.rootcommands.Shell;
|
||||||
import org.sufficientlysecure.rootcommands.Toolbox;
|
import org.sufficientlysecure.rootcommands.Toolbox;
|
||||||
|
|
||||||
@ -33,6 +31,9 @@ import java.io.IOException;
|
|||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
import de.greenrobot.event.EventBus;
|
||||||
|
import sharedcode.turboeditor.R;
|
||||||
|
import sharedcode.turboeditor.root.RootUtils;
|
||||||
|
import sharedcode.turboeditor.util.EventBusEvents;
|
||||||
|
|
||||||
public class SaveFileTask extends AsyncTask<Void, Void, Void> {
|
public class SaveFileTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
@ -100,7 +101,7 @@ public class SaveFileTask extends AsyncTask<Void, Void, Void> {
|
|||||||
protected void onPostExecute(final Void aVoid) {
|
protected void onPostExecute(final Void aVoid) {
|
||||||
super.onPostExecute(aVoid);
|
super.onPostExecute(aVoid);
|
||||||
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
|
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
|
||||||
if(message.equals(positiveMessage))
|
if (message.equals(positiveMessage))
|
||||||
EventBus.getDefault().post(new EventBusEvents.SavedAFile(filePath));
|
EventBus.getDefault().post(new EventBusEvents.SavedAFile(filePath));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,18 +17,20 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sharedcode.turboeditor.util;
|
package sharedcode.turboeditor.texteditor;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
public class EdittextPadding {
|
import sharedcode.turboeditor.util.PixelDipConverter;
|
||||||
|
|
||||||
|
public class EditTextPadding {
|
||||||
|
|
||||||
public static int getPaddingWithoutLineNumbers(Context context) {
|
public static int getPaddingWithoutLineNumbers(Context context) {
|
||||||
return (int) PixelDipConverter.convertDpToPixel(5, context);
|
return (int) PixelDipConverter.convertDpToPixel(5, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getPaddingWithLineNumbers(Context context, float fontSize) {
|
public static int getPaddingWithLineNumbers(Context context, float fontSize) {
|
||||||
return (int) PixelDipConverter.convertDpToPixel(fontSize * 1.85f, context);
|
return (int) PixelDipConverter.convertDpToPixel(fontSize * 2f, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getPaddingTop(Context context) {
|
public static int getPaddingTop(Context context) {
|
@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sharedcode.turboeditor.util;
|
package sharedcode.turboeditor.texteditor;
|
||||||
|
|
||||||
import org.mozilla.universalchardet.UniversalDetector;
|
import org.mozilla.universalchardet.UniversalDetector;
|
||||||
|
|
@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sharedcode.turboeditor.util;
|
package sharedcode.turboeditor.texteditor;
|
||||||
|
|
||||||
import android.text.Layout;
|
import android.text.Layout;
|
||||||
import android.widget.ScrollView;
|
import android.widget.ScrollView;
|
||||||
@ -34,23 +34,18 @@ public class LineUtils {
|
|||||||
return realLines;
|
return realLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getYAtLine(ScrollView scrollView, int lineCount, int line){
|
public int getYAtLine(ScrollView scrollView, int lineCount, int line) {
|
||||||
return scrollView.getChildAt(0).getHeight() / lineCount * line;
|
return scrollView.getChildAt(0).getHeight() / lineCount * line;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFirstVisibleLine(ScrollView scrollView, int lineCount){
|
public int getFirstVisibleLine(ScrollView scrollView, int childHeight, int lineCount) throws ArithmeticException {
|
||||||
return getFirstVisibleLine(scrollView, scrollView.getChildAt(0).getHeight(), lineCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFirstVisibleLine(ScrollView scrollView, int childHeight, int lineCount) throws ArithmeticException{
|
|
||||||
int line = (scrollView.getScrollY() * lineCount) / childHeight;
|
int line = (scrollView.getScrollY() * lineCount) / childHeight;
|
||||||
if (line < 0) line = 0;
|
if (line < 0) line = 0;
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLastVisibleLine(int firstVisibleLine, int lineCount) {
|
public int getLastVisibleLine(ScrollView scrollView, int childHeight, int lineCount, int deviceHeight) {
|
||||||
int line;
|
int line = ((scrollView.getScrollY() + deviceHeight) * lineCount) / childHeight;
|
||||||
line = firstVisibleLine + 150;
|
|
||||||
if (line > lineCount) line = lineCount;
|
if (line > lineCount) line = lineCount;
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
@ -90,6 +85,7 @@ public class LineUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the line from the index of the letter in the text
|
* Gets the line from the index of the letter in the text
|
||||||
|
*
|
||||||
* @param index
|
* @param index
|
||||||
* @param lineCount
|
* @param lineCount
|
||||||
* @param layout
|
* @param layout
|
||||||
@ -109,15 +105,19 @@ public class LineUtils {
|
|||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int firstReadLine() {
|
||||||
|
return realLines[0];
|
||||||
|
}
|
||||||
|
|
||||||
public int lastReadLine() {
|
public int lastReadLine() {
|
||||||
return realLines[realLines.length-1];
|
return realLines[realLines.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int fakeLineFromRealLine(int realLine) {
|
public int fakeLineFromRealLine(int realLine) {
|
||||||
int i;
|
int i;
|
||||||
int fakeLine = 0;
|
int fakeLine = 0;
|
||||||
for(i = 0; i < realLines.length; i++) {
|
for (i = 0; i < realLines.length; i++) {
|
||||||
if (realLine == realLines[i]){
|
if (realLine == realLines[i]) {
|
||||||
fakeLine = i;
|
fakeLine = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
@ -17,26 +17,23 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sharedcode.turboeditor.util;
|
package sharedcode.turboeditor.texteditor;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import sharedcode.turboeditor.preferences.PreferenceHelper;
|
||||||
|
|
||||||
public class PageSystem {
|
public class PageSystem {
|
||||||
|
|
||||||
public interface PageSystemInterface {
|
|
||||||
void onPageChanged(int page);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> pages;
|
private List<String> pages;
|
||||||
|
|
||||||
private int[] startingLines;
|
private int[] startingLines;
|
||||||
|
|
||||||
private int currentPage = 0;
|
private int currentPage = 0;
|
||||||
|
|
||||||
private PageSystemInterface pageSystemInterface;
|
private PageSystemInterface pageSystemInterface;
|
||||||
|
|
||||||
public PageSystem(PageSystemInterface pageSystemInterface, String text) {
|
public PageSystem(Context context, PageSystemInterface pageSystemInterface, String text) {
|
||||||
this.pageSystemInterface = pageSystemInterface;
|
this.pageSystemInterface = pageSystemInterface;
|
||||||
pages = new LinkedList<>();
|
pages = new LinkedList<>();
|
||||||
|
|
||||||
@ -46,8 +43,9 @@ public class PageSystem {
|
|||||||
int to;
|
int to;
|
||||||
int indexOfReturn;
|
int indexOfReturn;
|
||||||
int textLenght = text.length();
|
int textLenght = text.length();
|
||||||
if(textLenght > maxLenghtInOnePage) {
|
boolean pageSystemEnabled = PreferenceHelper.getSplitText(context);
|
||||||
while (i < textLenght) {
|
if (pageSystemEnabled && textLenght > maxLenghtInOnePage) {
|
||||||
|
while (i < textLenght && pageSystemEnabled) {
|
||||||
to = i + charForPage;
|
to = i + charForPage;
|
||||||
indexOfReturn = text.indexOf("\n", to);
|
indexOfReturn = text.indexOf("\n", to);
|
||||||
if (indexOfReturn > to) to = indexOfReturn;
|
if (indexOfReturn > to) to = indexOfReturn;
|
||||||
@ -78,8 +76,8 @@ public class PageSystem {
|
|||||||
public String getTextOfNextPages(boolean includeCurrent, int nOfPages) {
|
public String getTextOfNextPages(boolean includeCurrent, int nOfPages) {
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
int i;
|
int i;
|
||||||
for(i = includeCurrent ? 0 : 1; i < nOfPages; i++){
|
for (i = includeCurrent ? 0 : 1; i < nOfPages; i++) {
|
||||||
if(pages.size() > (currentPage + i)) {
|
if (pages.size() > (currentPage + i)) {
|
||||||
stringBuilder.append(pages.get(currentPage + 1));
|
stringBuilder.append(pages.get(currentPage + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,25 +90,25 @@ public class PageSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void nextPage() {
|
public void nextPage() {
|
||||||
if(!canReadNextPage()) return;
|
if (!canReadNextPage()) return;
|
||||||
goToPage(currentPage + 1);
|
goToPage(currentPage + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void prevPage() {
|
public void prevPage() {
|
||||||
if(!canReadPrevPage()) return;
|
if (!canReadPrevPage()) return;
|
||||||
goToPage(currentPage - 1);
|
goToPage(currentPage - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void goToPage(int page) {
|
public void goToPage(int page) {
|
||||||
if(page >= pages.size()) page = pages.size() - 1;
|
if (page >= pages.size()) page = pages.size() - 1;
|
||||||
if(page < 0) page = 0;
|
if (page < 0) page = 0;
|
||||||
boolean shouldUpdateLines = page > currentPage && canReadNextPage();
|
boolean shouldUpdateLines = page > currentPage && canReadNextPage();
|
||||||
if(shouldUpdateLines) {
|
if (shouldUpdateLines) {
|
||||||
String text = getCurrentPageText();
|
String text = getCurrentPageText();
|
||||||
int nOfNewLineNow = (text.length() - text.replace("\n", "").length()) + 1; // normally the last line is not counted so we have to add 1
|
int nOfNewLineNow = (text.length() - text.replace("\n", "").length()) + 1; // normally the last line is not counted so we have to add 1
|
||||||
int nOfNewLineBefore = startingLines[currentPage+1] - startingLines[currentPage];
|
int nOfNewLineBefore = startingLines[currentPage + 1] - startingLines[currentPage];
|
||||||
int difference = nOfNewLineNow - nOfNewLineBefore;
|
int difference = nOfNewLineNow - nOfNewLineBefore;
|
||||||
updateStartingLines(currentPage+1, difference);
|
updateStartingLines(currentPage + 1, difference);
|
||||||
}
|
}
|
||||||
currentPage = page;
|
currentPage = page;
|
||||||
pageSystemInterface.onPageChanged(page);
|
pageSystemInterface.onPageChanged(page);
|
||||||
@ -122,8 +120,8 @@ public class PageSystem {
|
|||||||
int nOfNewLines;
|
int nOfNewLines;
|
||||||
String text;
|
String text;
|
||||||
startingLines[0] = 0;
|
startingLines[0] = 0;
|
||||||
for(i = 1; i < pages.size(); i++) {
|
for (i = 1; i < pages.size(); i++) {
|
||||||
text = pages.get(i-1);
|
text = pages.get(i - 1);
|
||||||
nOfNewLines = text.length() - text.replace("\n", "").length() + 1;
|
nOfNewLines = text.length() - text.replace("\n", "").length() + 1;
|
||||||
startingLine = startingLines[i - 1] + nOfNewLines;
|
startingLine = startingLines[i - 1] + nOfNewLines;
|
||||||
startingLines[i] = startingLine;
|
startingLines[i] = startingLine;
|
||||||
@ -131,11 +129,11 @@ public class PageSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateStartingLines(int fromPage, int difference) {
|
public void updateStartingLines(int fromPage, int difference) {
|
||||||
if(difference == 0)
|
if (difference == 0)
|
||||||
return;
|
return;
|
||||||
int i;
|
int i;
|
||||||
if(fromPage < 1) fromPage = 1;
|
if (fromPage < 1) fromPage = 1;
|
||||||
for(i = fromPage; i < pages.size(); i++) {
|
for (i = fromPage; i < pages.size(); i++) {
|
||||||
startingLines[i] += difference;
|
startingLines[i] += difference;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,13 +142,15 @@ public class PageSystem {
|
|||||||
return pages.size() - 1;
|
return pages.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCurrentPage() { return currentPage; }
|
public int getCurrentPage() {
|
||||||
|
return currentPage;
|
||||||
|
}
|
||||||
|
|
||||||
public String getAllText(String currentPageText) {
|
public String getAllText(String currentPageText) {
|
||||||
pages.set(currentPage, currentPageText);
|
pages.set(currentPage, currentPageText);
|
||||||
int i;
|
int i;
|
||||||
StringBuilder allText = new StringBuilder();
|
StringBuilder allText = new StringBuilder();
|
||||||
for(i = 0; i < pages.size(); i++) {
|
for (i = 0; i < pages.size(); i++) {
|
||||||
allText.append(pages.get(i)).append("\n");
|
allText.append(pages.get(i)).append("\n");
|
||||||
}
|
}
|
||||||
return allText.toString();
|
return allText.toString();
|
||||||
@ -163,4 +163,8 @@ public class PageSystem {
|
|||||||
public boolean canReadPrevPage() {
|
public boolean canReadPrevPage() {
|
||||||
return currentPage >= 1;
|
return currentPage >= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface PageSystemInterface {
|
||||||
|
void onPageChanged(int page);
|
||||||
|
}
|
||||||
}
|
}
|
@ -17,28 +17,27 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sharedcode.turboeditor.util;
|
package sharedcode.turboeditor.texteditor;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.faizmalkani.floatingactionbutton.FloatingActionButton;
|
import com.faizmalkani.floatingactionbutton.FloatingActionButton;
|
||||||
|
|
||||||
import sharedcode.turboeditor.R;
|
import sharedcode.turboeditor.R;
|
||||||
|
|
||||||
public class PageSystemButtons {
|
public class PageSystemButtons {
|
||||||
|
|
||||||
private static final int TIME_TO_SHOW_FABS = 2000;
|
private static final int TIME_TO_SHOW_FABS = 2000;
|
||||||
|
final Handler handler = new Handler();
|
||||||
public interface PageButtonsInterface {
|
final Runnable runnable = new Runnable() {
|
||||||
public void nextPageClicked();
|
@Override
|
||||||
public void prevPageClicked();
|
public void run() {
|
||||||
public void pageSystemButtonLongClicked();
|
PageSystemButtons.this.next.setVisibility(View.GONE);
|
||||||
|
PageSystemButtons.this.prev.setVisibility(View.GONE);
|
||||||
public boolean canReadNextPage();
|
}
|
||||||
public boolean canReadPrevPage();
|
};
|
||||||
}
|
|
||||||
|
|
||||||
FloatingActionButton prev, next;
|
FloatingActionButton prev, next;
|
||||||
PageButtonsInterface pageButtonsInterface;
|
PageButtonsInterface pageButtonsInterface;
|
||||||
|
|
||||||
@ -53,10 +52,10 @@ public class PageSystemButtons {
|
|||||||
this.prev.setColor(context.getResources().getColor(R.color.fab_light));
|
this.prev.setColor(context.getResources().getColor(R.color.fab_light));
|
||||||
this.prev.setDrawable(context.getResources().getDrawable(R.drawable.ic_keyboard_arrow_left));
|
this.prev.setDrawable(context.getResources().getDrawable(R.drawable.ic_keyboard_arrow_left));
|
||||||
|
|
||||||
if(pageButtonsInterface.canReadNextPage())
|
if (pageButtonsInterface.canReadNextPage())
|
||||||
next.setVisibility(View.VISIBLE);
|
next.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
if(pageButtonsInterface.canReadPrevPage())
|
if (pageButtonsInterface.canReadPrevPage())
|
||||||
prev.setVisibility(View.VISIBLE);
|
prev.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
this.next.setOnClickListener(new View.OnClickListener() {
|
this.next.setOnClickListener(new View.OnClickListener() {
|
||||||
@ -90,23 +89,14 @@ public class PageSystemButtons {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
final Handler handler = new Handler();
|
|
||||||
final Runnable runnable = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
PageSystemButtons.this.next.setVisibility(View.GONE);
|
|
||||||
PageSystemButtons.this.prev.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public void updateVisibility(boolean autoHide) {
|
public void updateVisibility(boolean autoHide) {
|
||||||
|
|
||||||
if(pageButtonsInterface.canReadNextPage())
|
if (pageButtonsInterface.canReadNextPage())
|
||||||
PageSystemButtons.this.next.setVisibility(View.VISIBLE);
|
PageSystemButtons.this.next.setVisibility(View.VISIBLE);
|
||||||
else
|
else
|
||||||
PageSystemButtons.this.next.setVisibility(View.GONE);
|
PageSystemButtons.this.next.setVisibility(View.GONE);
|
||||||
|
|
||||||
if(pageButtonsInterface.canReadPrevPage())
|
if (pageButtonsInterface.canReadPrevPage())
|
||||||
PageSystemButtons.this.prev.setVisibility(View.VISIBLE);
|
PageSystemButtons.this.prev.setVisibility(View.VISIBLE);
|
||||||
else
|
else
|
||||||
PageSystemButtons.this.prev.setVisibility(View.GONE);
|
PageSystemButtons.this.prev.setVisibility(View.GONE);
|
||||||
@ -121,7 +111,7 @@ public class PageSystemButtons {
|
|||||||
else
|
else
|
||||||
prev.hideFab();*/
|
prev.hideFab();*/
|
||||||
|
|
||||||
if(autoHide) {
|
if (autoHide) {
|
||||||
handler.removeCallbacks(runnable);
|
handler.removeCallbacks(runnable);
|
||||||
handler.postDelayed(runnable, TIME_TO_SHOW_FABS);
|
handler.postDelayed(runnable, TIME_TO_SHOW_FABS);
|
||||||
} else {
|
} else {
|
||||||
@ -129,4 +119,16 @@ public class PageSystemButtons {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface PageButtonsInterface {
|
||||||
|
public void nextPageClicked();
|
||||||
|
|
||||||
|
public void prevPageClicked();
|
||||||
|
|
||||||
|
public void pageSystemButtonLongClicked();
|
||||||
|
|
||||||
|
public boolean canReadNextPage();
|
||||||
|
|
||||||
|
public boolean canReadPrevPage();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sharedcode.turboeditor.util;
|
package sharedcode.turboeditor.texteditor;
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@ -69,9 +69,9 @@ public class Patterns {
|
|||||||
"\\b(int|float|long|complex|str|unicode|list|tuple|bytearray|buffer|xrange|set|frozenset|dict|bool)|(True|False|None|self|NotImplemented|Ellipsis|__debug__|__file__)|(and|del|from|not|while|as|elif|global|or|with|assert|else|if|pass|yield|break|except|import|print|class|exec|in|raise|continue|finally|is|return|def|for|lambda|try)|(ArithmeticError|AssertionError|AttributeError|BaseException|DeprecationWarning|EnvironmentError|EOFError|Exception|FloatingPointError|FutureWarning|GeneratorExit|IOError|ImportError|ImportWarning|IndexError|KeyError|KeyboardInterrupt|LookupError|MemoryError|NameError|NotImplementedError|OSError|OverflowError|PendingDeprecationWarning|ReferenceError|RuntimeError|RuntimeWarning|StandardError|StopIteration|SyntaxError|SyntaxWarning|SystemError|SystemExit|TypeError|UnboundLocalError|UserWarning|UnicodeError|UnicodeWarning|UnicodeEncodeError|UnicodeDecodeError|UnicodeTranslateError|ValueError|Warning|WindowsError|ZeroDivisionError)\\b", Pattern.CASE_INSENSITIVE);
|
"\\b(int|float|long|complex|str|unicode|list|tuple|bytearray|buffer|xrange|set|frozenset|dict|bool)|(True|False|None|self|NotImplemented|Ellipsis|__debug__|__file__)|(and|del|from|not|while|as|elif|global|or|with|assert|else|if|pass|yield|break|except|import|print|class|exec|in|raise|continue|finally|is|return|def|for|lambda|try)|(ArithmeticError|AssertionError|AttributeError|BaseException|DeprecationWarning|EnvironmentError|EOFError|Exception|FloatingPointError|FutureWarning|GeneratorExit|IOError|ImportError|ImportWarning|IndexError|KeyError|KeyboardInterrupt|LookupError|MemoryError|NameError|NotImplementedError|OSError|OverflowError|PendingDeprecationWarning|ReferenceError|RuntimeError|RuntimeWarning|StandardError|StopIteration|SyntaxError|SyntaxWarning|SystemError|SystemExit|TypeError|UnboundLocalError|UserWarning|UnicodeError|UnicodeWarning|UnicodeEncodeError|UnicodeDecodeError|UnicodeTranslateError|ValueError|Warning|WindowsError|ZeroDivisionError)\\b", Pattern.CASE_INSENSITIVE);
|
||||||
|
|
||||||
public static final Pattern LUA_KEYWORDS = Pattern.compile(
|
public static final Pattern LUA_KEYWORDS = Pattern.compile(
|
||||||
"@[A-Za-z0-9_\\.]*|\\b(local|global|boolean|number|userdata)\\b|\\b(true|false|nil)\\b|\\b(return|then|while|and|break|do|else|elseif|end|for|function|if|in|not|or|repeat|until|thread|table)\\b" +
|
"@[A-Za-z0-9_\\.]*|\\b(local|global|boolean|number|userdata)\\b|\\b(true|false|nil)\\b|\\b(return|then|while|and|break|do|else|elseif|end|for|function|if|in|not|or|repeat|until|thread|table)\\b" +
|
||||||
"|(?i)\\b(editsetText|editText|inkey|touch|system.exit|system.expCall|system.getAppPath|system.getCardMnt|system.getSec|system.impCallActionSend|system.impCallActionView|system.setrun|system.setScreen|system.version|El_Psy_Congroo|canvas.drawCircle|canvas.drawCls|canvas.drawLine|canvas.drawRect|canvas.getBmpSize|canvas.getColor|canvas.getg|canvas.getviewSize|canvas.loadBmp|canvas.putCircle|canvas.putCls|canvas.putflush|canvas.putg|canvas.putLine|canvas.putRect|canvas.putrotg|canvas.putWork|canvas.saveBmp|canvas.setMainBmp|canvas.setWorkBmp|canvas.workCls|canvas.workflush|color|canvas.drawText|canvas.drawTextBox|canvas.drawTextCenter|canvas.drawTextRotate|canvas.putText|canvas.putTextBox|canvas.putTextRotate|http.addHeader|http.addParam|http.clrHeader|http.clrParam|http.get|http.post|http.setContentType|http.setPostFile|http.status|dialog|item.add|item.check|item.clear|item.list|item.radio|toast|sensor.getAccel|sensor.setdevAccel|sensor.setdevMagnet|sensor.setdevOrient|sensor.getGdirection|sensor.getMagnet|sensor.getOrient|sound.beep|sound.isPlay|sound.pause|sound.restart|sound.setSoundFile|sound.start|sound.stop|zip.addFile|zip.exec|zip.status|sock.close|sock.connectOpen|sock.getAddress|sock.listenOpen|sock.recv|sock.send|sprite.clear|sprite.define|sprite.init|sprite.move|sprite.put)\\b" +
|
"|(?i)\\b(editsetText|editText|inkey|touch|system.exit|system.expCall|system.getAppPath|system.getCardMnt|system.getSec|system.impCallActionSend|system.impCallActionView|system.setrun|system.setScreen|system.version|El_Psy_Congroo|canvas.drawCircle|canvas.drawCls|canvas.drawLine|canvas.drawRect|canvas.getBmpSize|canvas.getColor|canvas.getg|canvas.getviewSize|canvas.loadBmp|canvas.putCircle|canvas.putCls|canvas.putflush|canvas.putg|canvas.putLine|canvas.putRect|canvas.putrotg|canvas.putWork|canvas.saveBmp|canvas.setMainBmp|canvas.setWorkBmp|canvas.workCls|canvas.workflush|color|canvas.drawText|canvas.drawTextBox|canvas.drawTextCenter|canvas.drawTextRotate|canvas.putText|canvas.putTextBox|canvas.putTextRotate|http.addHeader|http.addParam|http.clrHeader|http.clrParam|http.get|http.post|http.setContentType|http.setPostFile|http.status|dialog|item.add|item.check|item.clear|item.list|item.radio|toast|sensor.getAccel|sensor.setdevAccel|sensor.setdevMagnet|sensor.setdevOrient|sensor.getGdirection|sensor.getMagnet|sensor.getOrient|sound.beep|sound.isPlay|sound.pause|sound.restart|sound.setSoundFile|sound.start|sound.stop|zip.addFile|zip.exec|zip.status|sock.close|sock.connectOpen|sock.getAddress|sock.listenOpen|sock.recv|sock.send|sprite.clear|sprite.define|sprite.init|sprite.move|sprite.put)\\b" +
|
||||||
"|(?i)\\b(assert|collectgarbage|coroutine.create|coroutine.resume|coroutine.running|coroutine.status|coroutine.wrap|coroutine.yield|debug.debug|debug.getfenv|debug.gethook|debug.getinfo|debug.getlocal|debug.getmetatable|debug.getregistry|debug.getupvalue|debug.setfenv|debug.sethook|debug.setlocal|debug.setmetatable|debug.setupvalue|debug.traceback|dofile|error|file:close|file:flush|file:lines|file:read|file:seek|file:setvbuf|file:write|getfenv|getmetatable|io.close|io.flush|io.input|io.lines|io.open|io.output|io.popen|io.read|io.tmpfile|io.type|io.write|ipairs|load|loadfile|loadstring|math.abs|math.acos|math.asin|math.atan2|math.atan|math.ceil|math.cosh|math.cos|math.deg|math.exp|math.floor|math.fmod|math.frexp|math.ldexp|math.log10|math.log|math.max|math.min|math.modf|math.pow|math.rad|math.random|math.randomseed|math.sinh|math.sin|math.sqrt|math.tanh|math.tan|module|next|os.clock|os.date|os.difftime|os.execute|os.exit|os.getenv|os.remove|os.rename|os.setlocale|os.time|os.tmpname|package.cpath|package.loaded|package.loadlib|package.path|package.preload|package.seeal|pairs|pcall|print|rawequal|rawget|rawset|require|select|setfenv|setmetatable|string.byte|string.char|string.dump|string.find|string.format|string.gmatch|string.gsub|string.len|string.lower|string.match|string.rep|string.reverse|string.sub|string.upper|table.concat|table.insert|table.maxn|table.remove|table.sort|tonumber|tostring|type|unpack|xpcall)\\b"
|
"|(?i)\\b(assert|collectgarbage|coroutine.create|coroutine.resume|coroutine.running|coroutine.status|coroutine.wrap|coroutine.yield|debug.debug|debug.getfenv|debug.gethook|debug.getinfo|debug.getlocal|debug.getmetatable|debug.getregistry|debug.getupvalue|debug.setfenv|debug.sethook|debug.setlocal|debug.setmetatable|debug.setupvalue|debug.traceback|dofile|error|file:close|file:flush|file:lines|file:read|file:seek|file:setvbuf|file:write|getfenv|getmetatable|io.close|io.flush|io.input|io.lines|io.open|io.output|io.popen|io.read|io.tmpfile|io.type|io.write|ipairs|load|loadfile|loadstring|math.abs|math.acos|math.asin|math.atan2|math.atan|math.ceil|math.cosh|math.cos|math.deg|math.exp|math.floor|math.fmod|math.frexp|math.ldexp|math.log10|math.log|math.max|math.min|math.modf|math.pow|math.rad|math.random|math.randomseed|math.sinh|math.sin|math.sqrt|math.tanh|math.tan|module|next|os.clock|os.date|os.difftime|os.execute|os.exit|os.getenv|os.remove|os.rename|os.setlocale|os.time|os.tmpname|package.cpath|package.loaded|package.loadlib|package.path|package.preload|package.seeal|pairs|pcall|print|rawequal|rawget|rawset|require|select|setfenv|setmetatable|string.byte|string.char|string.dump|string.find|string.format|string.gmatch|string.gsub|string.len|string.lower|string.match|string.rep|string.reverse|string.sub|string.upper|table.concat|table.insert|table.maxn|table.remove|table.sort|tonumber|tostring|type|unpack|xpcall)\\b"
|
||||||
);
|
);
|
||||||
|
|
||||||
public static final Pattern PHP_VARIABLES = Pattern.compile("\\$\\s*(\\w+)");
|
public static final Pattern PHP_VARIABLES = Pattern.compile("\\$\\s*(\\w+)");
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user