1
mirror of https://github.com/jlelse/teleposter synced 2024-06-06 00:56:28 +00:00

Compare commits

...

49 Commits

Author SHA1 Message Date
ed27844fa9 1.5.5 2020-10-31 22:16:59 +01:00
e99b487218 1.5.4 2019-06-07 07:51:32 +02:00
792bb627c8 Update dependencies 2019-06-07 07:40:12 +02:00
e47cfe7d38 Update Material Dialogs 2019-03-24 15:31:30 +01:00
dependabot[bot]
dda25c44ec Bump gradle from 3.3.1 to 3.3.2 (#22)
Bumps gradle from 3.3.1 to 3.3.2.

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-03-24 15:20:41 +01:00
dependabot[bot]
0d80011ac3 Bump input from 2.0.0 to 2.0.3 (#21)
Bumps input from 2.0.0 to 2.0.3.

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-03-01 18:32:41 +01:00
dependabot[bot]
02fb6bb3ae Bump core from 2.0.0 to 2.0.3 (#20)
Bumps core from 2.0.0 to 2.0.3.

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-03-01 18:27:50 +01:00
dependabot[bot]
a3343e1f30 Bump Android-AdvancedWebView from 3.1.3 to v3.2.0 (#15)
Bumps [Android-AdvancedWebView](https://github.com/delight-im/Android-AdvancedWebView) from 3.1.3 to v3.2.0.
- [Release notes](https://github.com/delight-im/Android-AdvancedWebView/releases)
- [Commits](https://github.com/delight-im/Android-AdvancedWebView/compare/v3.1.3...v3.2.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-03-01 18:10:10 +01:00
bf384a8f59 1.5.3 2019-02-10 10:59:06 +01:00
1d00e34219 Small fix 2019-02-10 10:53:48 +01:00
3946d21e68 Improve HTML 2019-02-10 10:46:36 +01:00
dependabot[bot]
9857315274 Bump input from 2.0.0-rc11 to 2.0.0 (#12)
Bumps input from 2.0.0-rc11 to 2.0.0.

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-02-10 10:21:53 +01:00
dependabot[bot]
cfe2950b34 Bump core from 2.0.0-rc11 to 2.0.0 (#11)
Bumps core from 2.0.0-rc11 to 2.0.0.

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-02-10 10:19:12 +01:00
dependabot[bot]
b989b775b4 Bump kotlin_version from 1.3.20 to 1.3.21 (#14)
Bumps `kotlin_version` from 1.3.20 to 1.3.21.

Updates `kotlin-gradle-plugin` from 1.3.20 to 1.3.21
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.3.20...v1.3.21)

Updates `kotlin-stdlib` from 1.3.20 to 1.3.21
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.3.20...v1.3.21)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-02-10 10:18:58 +01:00
dependabot[bot]
5c6476e99a Bump gradle from 3.3.0 to 3.3.1 (#13)
Bumps gradle from 3.3.0 to 3.3.1.

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-02-10 10:18:41 +01:00
dependabot[bot]
35bada0699 Bump input from 2.0.0-rc10 to 2.0.0-rc11 (#10)
Bumps input from 2.0.0-rc10 to 2.0.0-rc11.

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-02-06 08:23:26 +01:00
dependabot[bot]
cb7f3b7dd1 Bump core from 2.0.0-rc10 to 2.0.0-rc11 (#9)
Bumps core from 2.0.0-rc10 to 2.0.0-rc11.

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-02-06 07:58:24 +01:00
2957a2f250 Fixes and improvements 2019-02-05 22:18:51 +01:00
c93a7ae575 Upgrade Fuel to 2.0.1 (also bump min sdk to 19 - required for update) 2019-02-05 20:58:42 +01:00
b17d8802a5 Update Material Dialogs Input library 2019-02-05 20:21:45 +01:00
dependabot[bot]
7ef293950e Bump core from 2.0.0-rc7 to 2.0.0-rc10 (#7)
Bumps core from 2.0.0-rc7 to 2.0.0-rc10.

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-02-05 20:12:10 +01:00
dependabot[bot]
07539e18d7 Bump kotlin_version from 1.3.11 to 1.3.20 (#8)
Bumps `kotlin_version` from 1.3.11 to 1.3.20.

Updates `kotlin-gradle-plugin` from 1.3.11 to 1.3.20
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.3.11...v1.3.20)

Updates `kotlin-stdlib` from 1.3.11 to 1.3.20
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.3.11...v1.3.20)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-02-05 20:11:43 +01:00
Licaon_Kter
cb6291be6b Remove uneeded reps (#4)
...this also blocked F-Droid.
2019-02-05 19:55:02 +01:00
57140d34e2 1.5.2 2019-01-23 17:36:46 +01:00
florian19982
207ef7fdf0 Added i18n for German (#3) 2018-10-06 20:40:34 +02:00
e4443b95dd Migrate to AndroidX 2018-09-22 08:18:57 +02:00
fc561cf3e5 Update Gradle wrapper 2018-09-13 21:27:08 +02:00
0ec5066b18 Dependency upgrades, basic bug fixing and min API bump 2018-09-11 22:24:39 +02:00
041137004c Update Gradle wrapper 2018-09-11 20:51:33 +02:00
Jan-Lukas Else
b2065a0fcd
Merge pull request #2 from Poussinou/patch-1
Update README.md
2018-08-20 07:46:29 +02:00
Poussinou
3e16b85e94
Update README.md 2018-08-11 15:25:46 +02:00
4ef87824a8 1.5.1 2018-07-29 08:47:28 +02:00
58490c8096 Update libraries 2018-07-29 08:39:18 +02:00
b80f0a0088 Update libraries 2018-05-30 17:54:33 +02:00
95fbde01e6 Update Gradle Wrapper 2018-05-30 17:46:28 +02:00
ac5335af86 1.5 2018-02-14 19:24:11 +01:00
1a5c508414 Fix displaying author 2018-02-14 19:23:45 +01:00
f63385d1d1 Fix displaying author 2018-02-14 19:10:58 +01:00
62bfb2059f Remove reference to unused library 2018-02-14 19:02:20 +01:00
c59258af1e Remove editor border 2018-02-14 19:00:37 +01:00
bddc725fcb Change color scheme 2018-02-14 18:57:18 +01:00
72dd10a14a Add Login help, polish menu 2018-02-14 18:51:20 +01:00
3e704f3080 Enable login 2018-02-14 18:13:55 +01:00
d82166935f Add API method to login (untested) 2018-02-12 21:56:36 +01:00
e9f035e260 Add some style options to editor, remove useless strings 2018-02-12 19:54:07 +01:00
f8bc76157a Viewer class 2018-02-12 19:36:19 +01:00
459a1b98f8 Fix some editor bugs 2018-02-12 18:18:16 +01:00
4ccb45df39 Move image upload to JS part 2018-02-12 17:59:30 +01:00
fe09e464bf Update Fuel library 2018-02-12 15:45:01 +01:00
25 changed files with 793 additions and 491 deletions

View File

@ -8,6 +8,13 @@ For more information about Telegra.ph visit https://telegram.org/blog/instant-vi
Please take care, that this app might be unstable due to it's early development state! Please take care, that this app might be unstable due to it's early development state!
[<img src="https://f-droid.org/badge/get-it-on.png"
alt="Get it on F-Droid"
height="90">](https://f-droid.org/packages/telegra.ph/)
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png"
alt="Get it on Google Play"
height="90">](https://play.google.com/store/apps/details?id=telegra.ph)
## LICENSE ## LICENSE
``` ```

View File

@ -2,19 +2,19 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
android { android {
compileSdkVersion 27 compileSdkVersion 30
buildToolsVersion "27.0.3" buildToolsVersion "30.0.2"
defaultConfig { defaultConfig {
applicationId "telegra.ph" applicationId "telegra.ph"
minSdkVersion 15 minSdkVersion 19
targetSdkVersion 27 targetSdkVersion 30
versionCode 12 versionCode 18
versionName "1.4.1" versionName "1.5.5"
resConfigs "en" resConfigs "en", "de", "es", "tr", "ru"
} }
buildTypes { buildTypes {
debug { debug {
minifyEnabled true minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
applicationIdSuffix '.debug' applicationIdSuffix '.debug'
versionNameSuffix ' debug' versionNameSuffix ' debug'
@ -24,16 +24,19 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
} }
lintOptions {
abortOnError false
}
} }
dependencies { dependencies {
implementation 'com.android.support:appcompat-v7:27.0.2' implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.android.support:recyclerview-v7:27.0.2' implementation 'androidx.preference:preference-ktx:1.1.1'
implementation 'com.android.support:support-v13:27.0.2'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'com.github.delight-im:Android-AdvancedWebView:v3.0.0' implementation 'com.github.delight-im:Android-AdvancedWebView:3.2.1'
implementation 'com.afollestad.material-dialogs:core:0.9.6.0' implementation 'com.afollestad.material-dialogs:core:3.3.0'
implementation 'com.afollestad.material-dialogs:commons:0.9.6.0' implementation 'com.afollestad.material-dialogs:input:3.3.0'
implementation 'pub.devrel:easypermissions:1.1.3' implementation 'com.github.kittinunf.fuel:fuel:2.3.0'
implementation 'com.github.kittinunf.fuel:fuel-android:1.12.0' implementation 'com.github.kittinunf.fuel:fuel-android:2.3.0'
implementation 'com.github.kittinunf.fuel:fuel-json:2.3.0'
} }

View File

@ -32,6 +32,9 @@
<data android:scheme="http" /> <data android:scheme="http" />
<data android:scheme="https" /> <data android:scheme="https" />
<data android:host="telegra.ph" /> <data android:host="telegra.ph" />
<data android:host="graph.org" />
<data android:host="edit.telegra.ph" />
<data android:host="edit.graph.org" />
</intent-filter> </intent-filter>
</activity> </activity>
</application> </application>

View File

@ -1,78 +1,118 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" <link
rel="stylesheet"> href="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.18/summernote-lite.css"
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script> rel="stylesheet"
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script> />
<link href="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.9/summernote.css" <style>
rel="stylesheet"> * {
<script src="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.9/summernote.js"></script> max-width: 100% !important;
<style> * { max-width: 100%; height: auto; word-break: break-all; word-break: break-word; } height: auto;
word-break: break-all;
word-break: break-word;
}
</style> #summernote {
</head> width: 100%;
<body> height: 100%;
<div id="summernote" style="width:100%;height:100%"></div> }
<script>
function domToNode(domNode) { .note-editor {
border: none !important;
}
</style>
</head>
<body>
<div id="summernote"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.18/summernote-lite.min.js"></script>
<script>
function domToNode(domNode) {
if (domNode.nodeType == domNode.TEXT_NODE) { if (domNode.nodeType == domNode.TEXT_NODE) {
return domNode.data; return domNode.data;
} }
if (domNode.nodeType != domNode.ELEMENT_NODE) { if (domNode.nodeType != domNode.ELEMENT_NODE) {
return false; return false;
} }
var nodeElement = {}; var nodeElement = {};
nodeElement.tag = domNode.tagName.toLowerCase(); nodeElement.tag = domNode.tagName.toLowerCase();
for (var i = 0; i < domNode.attributes.length; i++) { for (var i = 0; i < domNode.attributes.length; i++) {
var attr = domNode.attributes[i]; var attr = domNode.attributes[i];
if (attr.name == 'href' || attr.name == 'src') { if (attr.name == "href" || attr.name == "src") {
if (!nodeElement.attrs) { if (!nodeElement.attrs) {
nodeElement.attrs = {}; nodeElement.attrs = {};
}
nodeElement.attrs[attr.name] = attr.value;
} }
nodeElement.attrs[attr.name] = attr.value;
}
} }
if (domNode.childNodes.length > 0) { if (domNode.childNodes.length > 0) {
nodeElement.children = []; nodeElement.children = [];
for (var ii = 0; ii < domNode.childNodes.length; ii++) { for (var ii = 0; ii < domNode.childNodes.length; ii++) {
var child = domNode.childNodes[ii]; var child = domNode.childNodes[ii];
nodeElement.children.push(domToNode(child)); nodeElement.children.push(domToNode(child));
} }
} }
return nodeElement; return nodeElement;
} }
function getNodeJson() { function getNodeJson() {
window.android.getText(JSON.stringify(domToNode(document.getElementsByClassName('note-editable')[0]).children)); window.android.getText(
} JSON.stringify(
domToNode(document.getElementsByClassName("note-editable")[0])
.children
)
);
}
</script> function uploadImage(file) {
<script> data = new FormData();
$(document).ready(function () { data.append("FileUpload", file);
$('#summernote').summernote({ $.ajax({
height: 1200, data: data,
focus: true, type: "POST",
placeholder: '', url: "https://telegra.ph/upload",
toolbar: [ cache: false,
// [groupName, [list of button]] contentType: false,
['style', ['bold', 'italic']], processData: false,
['para', ['ul', 'ol']], success: function(data) {
['insert', ['link']], if (data) {
['history', ['undo', 'redo']], $("#summernote").summernote("insertImage", data[0].src);
['other', ['codeview']]
],
callbacks: {
onInit: function (e) {
$("#summernote").summernote("fullscreen.toggle");
}
} }
}
}); });
}); }
</script> $(document).ready(function() {
</body> $("#summernote").summernote({
focus: true,
placeholder: "Start writing...",
styleTags: ["p", "h3", "h4", "blockquote", "pre"],
toolbar: [
["style", ["style", "bold", "italic", "underline", "clear"]],
["para", ["ul", "ol"]],
["insert", ["link", "picture", "hr"]],
["history", ["undo", "redo"]],
["other", ["codeview"]]
],
callbacks: {
onInit: function(e) {
$("#summernote").summernote("fullscreen.toggle");
},
onImageUpload: function(files) {
uploadImage(files[0]);
}
}
});
});
function setContent(content) {
$("#summernote").summernote("code", content);
}
</script>
</body>
</html> </html>

View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.min.css"
/>
<style>
* {
max-width: 100% !important;
height: auto;
word-break: break-all;
word-break: break-word;
}
</style>
</head>
<body>
<main role="main" class="container">
<div id="viewerTitle" class="mt-3"></div>
<div id="viewerAuthor"></div>
<div id="viewerViews"></div>
<div id="viewerContent"></div>
</main>
<script>
function setTitle(title) {
document.getElementById("viewerTitle").innerHTML =
"<h1>" + title + "</h1>";
}
function setAuthor(author, url) {
var viewerAuthor = document.getElementById("viewerAuthor");
if (author && url && author.length > 0 && url.length > 0)
viewerAuthor.innerHTML =
'By <a href="' + url + '">' + author + "</a><br>";
else if (author && author.length > 0)
viewerAuthor.innerHTML = "By " + author + "<br>";
else if (url && url.length > 0)
viewerAuthor.innerHTML =
'By <a href="' + url + '"><i>Author</i></a><br>';
else viewerAuthor.innerHTML = "";
}
function setViews(views) {
document.getElementById("viewerViews").innerHTML =
views + " times viewed<br><br>";
}
function setDescription(description) {
document.getElementById("viewerContent").innerHTML = description;
}
function setContent(content) {
document.getElementById("viewerContent").innerHTML = content;
}
</script>
</body>
</html>

View File

@ -4,54 +4,37 @@ import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.webkit.JavascriptInterface import android.webkit.JavascriptInterface
import android.webkit.WebSettings import im.delight.android.webview.AdvancedWebView
import android.webkit.WebView
import android.webkit.WebViewClient
class Editor : WebView { class Editor @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AdvancedWebView(context, attrs, defStyleAttr) {
private var getCallback: (json: String?) -> Unit? = {} private var getCallback: (json: String?) -> Unit? = {}
constructor(context: Context) : super(context) { init {
init() prepare()
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init()
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
init()
} }
@SuppressLint("SetJavaScriptEnabled", "AddJavascriptInterface") @SuppressLint("SetJavaScriptEnabled", "AddJavascriptInterface")
private fun init() { fun prepare() {
this.settings.javaScriptEnabled = true this.settings.javaScriptEnabled = true
this.settings.cacheMode = WebSettings.LOAD_NO_CACHE
this.addJavascriptInterface(MyJavaScriptInterface(), "android") this.addJavascriptInterface(MyJavaScriptInterface(), "android")
this.settings.loadWithOverviewMode = true this.settings.loadWithOverviewMode = true
this.settings.useWideViewPort = true this.settings.useWideViewPort = true
this.loadDataWithBaseURL("http://telegra.ph", context.assets.open("editor.html").bufferedReader().readText(), "text/html", "utf-8", null) setMixedContentAllowed(true)
this.loadDataWithBaseURL("https://telegra.ph", context.assets.open("editor.html").bufferedReader().readText(), "text/html", "utf-8", null)
} }
private inner class MyJavaScriptInterface { private inner class MyJavaScriptInterface {
@JavascriptInterface @JavascriptInterface
@SuppressWarnings("unused")
fun getText(json: String) { fun getText(json: String) {
getCallback(json) getCallback(json)
} }
} }
fun setText(html: String) { fun setContent(content: String?) {
webViewClient = object : WebViewClient() { this.loadUrl("javascript:setContent('${content?.replace("'", "\\'")}');")
override fun onPageFinished(view: WebView, url: String) {
setText(html)
}
}
this.loadUrl("javascript:$('#summernote').summernote('reset');")
this.loadUrl("javascript:$('#summernote').summernote('code', '" + html.replace("'", "\\'") + "');")
}
fun addImage(url: String) {
this.loadUrl("javascript:$('#summernote').summernote('insertImage', '$url');")
} }
fun getText(callback: (json: String?) -> Unit) { fun getText(callback: (json: String?) -> Unit) {

View File

@ -2,23 +2,69 @@ package telegra.ph
import android.content.Intent import android.content.Intent
import android.graphics.Bitmap import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.support.v7.app.AppCompatActivity
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 androidx.appcompat.app.AppCompatActivity
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.folderselector.FileChooserDialog import com.afollestad.materialdialogs.input.input
import com.afollestad.materialdialogs.list.listItemsMultiChoice
import com.afollestad.materialdialogs.list.listItemsSingleChoice
import im.delight.android.webview.AdvancedWebView import im.delight.android.webview.AdvancedWebView
import pub.devrel.easypermissions.AfterPermissionGranted import java.net.URI
import pub.devrel.easypermissions.EasyPermissions
import java.io.File
class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserDialog.FileCallback { class MainActivity : AppCompatActivity() {
private val webView: AdvancedWebView? by lazy { findViewById<AdvancedWebView?>(R.id.webView) } private val viewer: Viewer? by lazy {
private val editor: Editor? by lazy { findViewById<Editor?>(R.id.editor) } findViewById<Viewer?>(R.id.viewer)?.apply {
setListener(this@MainActivity, object : AdvancedWebView.Listener {
override fun onPageFinished(url: String?) {
viewerPendingPage?.let { viewer?.showPage(it) }
viewerPendingPage = null
}
override fun onPageError(errorCode: Int, description: String?, failingUrl: String?) {
}
override fun onDownloadRequested(url: String?, suggestedFilename: String?, mimeType: String?, contentLength: Long, contentDisposition: String?, userAgent: String?) {
}
override fun onExternalPageRequest(url: String?) {
AdvancedWebView.Browsers.openUrl(this@MainActivity, url)
}
override fun onPageStarted(url: String?, favicon: Bitmap?) {
}
})
}
}
private var viewerPendingPage: TelegraphApi.Page? = null
private val editor: Editor? by lazy {
findViewById<Editor?>(R.id.editor)?.apply {
setListener(this@MainActivity, object : AdvancedWebView.Listener {
override fun onPageFinished(url: String?) {
editorPendingPage?.let { editor?.setContent(it.content) }
editorPendingPage = null
}
override fun onPageError(errorCode: Int, description: String?, failingUrl: String?) {
}
override fun onDownloadRequested(url: String?, suggestedFilename: String?, mimeType: String?, contentLength: Long, contentDisposition: String?, userAgent: String?) {
}
override fun onExternalPageRequest(url: String?) {
AdvancedWebView.Browsers.openUrl(this@MainActivity, url)
}
override fun onPageStarted(url: String?, favicon: Bitmap?) {
}
})
}
}
private var editorPendingPage: TelegraphApi.Page? = null
private var currentUrl = ""
private var currentPage: TelegraphApi.Page? = null private var currentPage: TelegraphApi.Page? = null
private var editorMode = true private var editorMode = true
private var canEdit = false private var canEdit = false
@ -27,159 +73,104 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserD
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
webView?.apply { if (accessToken.isBlank()) TelegraphApi.createAccount(shortName = "teleposter") { success, account, error ->
setListener(this@MainActivity, this@MainActivity)
setMixedContentAllowed(true)
setCookiesEnabled(true)
setThirdPartyCookiesEnabled(true)
addPermittedHostname("telegra.ph")
isHorizontalScrollBarEnabled = false
isVerticalScrollBarEnabled = false
overScrollMode = View.OVER_SCROLL_NEVER
}
if (accessToken().isBlank()) TelegraphApi.createAccount(shortName = "teleposter") { success, account, error ->
if (success && account != null && account.accessToken != null) { if (success && account != null && account.accessToken != null) {
saveAccessToken(account.accessToken) accessToken = account.accessToken
} else { } else {
showError(error) showError(error)
} }
} }
if (intent.action == Intent.ACTION_VIEW && intent.dataString.contains("telegra.ph")) loadPage(intent.dataString.split("/").last()) if (intent.action == Intent.ACTION_VIEW) {
else loadEditor() val uri = URI.create(intent.dataString)
when (uri.host) {
"telegra.ph", "graph.org" -> loadPage(uri.path)
"edit.telegra.ph", "edit.graph.org" -> login(uri.toString())
}
}
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
if (intent?.action == Intent.ACTION_VIEW) {
val uri = URI.create(intent.dataString)
when (uri.host) {
"telegra.ph", "graph.org" -> loadPage(uri.path)
"edit.telegra.ph", "edit.graph.org" -> login(uri.toString())
}
}
} }
private fun loadEditor(path: String? = null) { private fun loadEditor(path: String? = null) {
runOnUiThread { editorMode = true
editorMode = true canEdit = false
canEdit = false isEdit = false
isEdit = false invalidateOptionsMenu()
invalidateOptionsMenu() editor?.visibility = View.VISIBLE
editor?.visibility = View.VISIBLE viewer?.visibility = View.GONE
webView?.visibility = View.GONE currentPage = null
currentPage = null // Load
// Load if (path != null) TelegraphApi.getPage(accessToken, path, true) { success, page, error ->
if (path != null) TelegraphApi.getPage(accessToken(), path, true) { success, page, error -> if (success && page != null) {
if (success && page != null) { isEdit = true
isEdit = true currentPage = page
currentPage = page editorPendingPage = page
editor?.setText(page.content ?: "") editor?.prepare()
} else { } else {
showError(error) showError(error)
}
} }
} else {
editor?.prepare()
}
}
private fun login(authUrl: String) {
TelegraphApi.login(authUrl) { success, accessToken, account ->
if (success && !accessToken.isNullOrEmpty()) {
this.accessToken = accessToken
this.authorName = account?.authorName
showMessage(getString(R.string.success), getString(R.string.login_success))
} else showError(getString(R.string.login_failed))
} }
} }
private fun loadPage(path: String) { private fun loadPage(path: String) {
runOnUiThread { editorMode = false
editorMode = false canEdit = false
canEdit = false invalidateOptionsMenu()
invalidateOptionsMenu() viewer?.visibility = View.VISIBLE
webView?.visibility = View.VISIBLE editor?.visibility = View.GONE
editor?.visibility = View.GONE currentPage = null
currentPage = null // Load
// Load TelegraphApi.getPage(accessToken, path, true) { success, page, error ->
TelegraphApi.getPage(accessToken(), path, true) { success, page, error -> if (success && page != null) {
if (success && page != null) showPage(page) canEdit = page.canEdit ?: false
else showError(error) invalidateOptionsMenu()
currentPage = page
viewerPendingPage = page
viewer?.prepare()
} }
}
}
private fun showPage(page: TelegraphApi.Page?) {
runOnUiThread {
editorMode = false
canEdit = page?.canEdit ?: false
invalidateOptionsMenu()
webView?.visibility = View.VISIBLE
editor?.visibility = View.GONE
currentPage = page
webView?.clearHistory()
// Show
page?.let {
var html = getString(R.string.viewer_html_head)
html += "<h1>${it.title}</h1>"
if (!it.authorName.isNullOrBlank() && !it.authorUrl.isNullOrBlank()) html += "<a href=\"${it.authorUrl}\">${it.authorName}</a><br>"
else if (!it.authorName.isNullOrBlank()) html += "${it.authorName}<br>"
if (it.views != 0) html += "${it.views} times viewed<br><br>"
html += if (it.content.isNullOrBlank()) it.description.replace("\n", "<br>") else it.content
html += getString(R.string.viewer_html_end)
webView?.loadDataWithBaseURL(it.url, html, "text/html; charset=UTF-8", null, null)
currentUrl = it.url
}
}
}
private fun showError(message: String? = null) {
runOnUiThread {
MaterialDialog.Builder(this)
.title(R.string.error)
.content(message ?: getString(R.string.error_desc))
.positiveText(android.R.string.ok)
.show()
}
}
@AfterPermissionGranted(100)
private fun uploadImage() {
if (EasyPermissions.hasPermissions(this, "android.permission.READ_EXTERNAL_STORAGE")) {
FileChooserDialog.Builder(this)
.mimeType("image/*")
.show(this)
} else {
EasyPermissions.requestPermissions(this, "", 100, "android.permission.READ_EXTERNAL_STORAGE")
}
}
override fun onPageFinished(url: String?) {
}
override fun onPageStarted(url: String?, favicon: Bitmap?) {
}
override fun onPageError(errorCode: Int, description: String?, failingUrl: String?) {
}
override fun onDownloadRequested(url: String?, suggestedFilename: String?, mimeType: String?, contentLength: Long, contentDisposition: String?, userAgent: String?) {
}
override fun onExternalPageRequest(url: String?) {
AdvancedWebView.Browsers.openUrl(this, url)
}
override fun onFileSelection(p0: FileChooserDialog, file: File) {
TelegraphApi.uploadImage(file) { success, src, error ->
if (success && src != null && src.isNotBlank())
editor?.addImage(src)
else showError(error) else showError(error)
} }
} }
override fun onFileChooserDismissed(p0: FileChooserDialog) { private fun showError(message: String? = null) = showMessage(getString(R.string.error), message
} ?: getString(R.string.error_desc))
override fun onResume() { private fun showMessage(title: String? = null, message: String? = null) {
super.onResume() MaterialDialog(this@MainActivity)
webView?.onResume() .title(text = title ?: "")
} .message(text = message ?: "")
.positiveButton(android.R.string.ok)
override fun onPause() { .show()
webView?.onPause()
super.onPause()
}
override fun onDestroy() {
webView?.onDestroy()
super.onDestroy()
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
webView?.onActivityResult(requestCode, resultCode, data) editor?.onActivityResult(requestCode, resultCode, data)
} }
override fun onBackPressed() { override fun onBackPressed() {
if (webView?.onBackPressed() == false) return if (viewer?.onBackPressed() == false) return
else super.onBackPressed() else super.onBackPressed()
} }
@ -202,39 +193,35 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserD
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) { return when (item.itemId) {
R.id.image -> {
uploadImage()
true
}
R.id.create -> { R.id.create -> {
loadEditor() loadEditor()
true true
} }
R.id.publish -> { R.id.publish -> {
editor?.getText { json -> editor?.getText { json ->
MaterialDialog.Builder(this) MaterialDialog(this@MainActivity)
.title(R.string.title_question) .title(R.string.title_question)
.input(getString(R.string.title_hint), currentPage?.title .input(hintRes = R.string.title_hint, prefill = currentPage?.title
?: "", { _, title -> ?: "", allowEmpty = false) { _, title ->
MaterialDialog.Builder(this) MaterialDialog(this@MainActivity)
.title(R.string.name_question) .title(R.string.name_question)
.input(getString(R.string.name_hint), if (isEdit) currentPage?.authorName .input(hintRes = R.string.name_hint, prefill = if (isEdit) currentPage?.authorName
?: authorName() ?: "" else authorName() ?: authorName ?: "" else authorName
?: "", { _, name -> ?: "", allowEmpty = true) { _, name ->
if (!isEdit) saveAuthorName(name.toString()) if (!isEdit) authorName = name.toString()
if (isEdit) TelegraphApi.editPage(accessToken(), currentPage?.path if (isEdit) TelegraphApi.editPage(accessToken, currentPage?.path
?: "", authorName = name.toString(), title = title.toString(), content = json ?: "", authorName = name.toString(), title = title.toString(), content = json
?: "", returnContent = true) { success, page, error -> ?: "", returnContent = true) { success, page, error ->
if (success && page != null) showPage(page) if (success && page != null) loadPage(page.path)
else showError(error) else showError(error)
} else TelegraphApi.createPage(accessToken(), content = json } else TelegraphApi.createPage(accessToken, content = json
?: "", title = title.toString(), authorName = name.toString(), returnContent = true) { success, page, error -> ?: "", title = title.toString(), authorName = name.toString(), returnContent = true) { success, page, error ->
if (success && page != null) showPage(page) if (success && page != null) loadPage(page.path)
else showError(error) else showError(error)
} }
}) }
.show() .show()
}) }
.show() .show()
} }
true true
@ -244,36 +231,44 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserD
true true
} }
R.id.bookmarks -> { R.id.bookmarks -> {
MaterialDialog.Builder(this) MaterialDialog(this@MainActivity)
.title(R.string.bookmarks) .title(R.string.bookmarks)
.positiveText(android.R.string.ok) .positiveButton(R.string.open)
.items(bookmarks().reversed().map { it.second }) .negativeButton(android.R.string.cancel)
.itemsCallback { _, _, i, _ -> .listItemsSingleChoice(items = bookmarks().reversed().map { it.second }) { _, index, _ ->
loadPage(bookmarks().reversed().map { it.first }[i]) loadPage(bookmarks().reversed().map { it.first }[index])
} }
.itemsLongCallback { _, _, i, _ -> .show()
MaterialDialog.Builder(this) true
}
R.id.delete_bookmark -> {
MaterialDialog(this@MainActivity)
.title(R.string.delete_bookmark)
.positiveButton(R.string.delete)
.negativeButton(android.R.string.cancel)
.listItemsMultiChoice(items = bookmarks().reversed().map { it.second }) { _, indices, _ ->
MaterialDialog(this@MainActivity)
.title(R.string.delete) .title(R.string.delete)
.content(R.string.delete_question) .message(R.string.delete_question)
.positiveText(android.R.string.yes) .positiveButton(R.string.yes)
.negativeText(android.R.string.no) .negativeButton(R.string.no)
.onPositive { _, _ -> .positiveButton {
deleteBookmark(bookmarks().reversed().map { it.first }[i]) val tmpBookmarks = bookmarks().reversed().map { it.first }
for (index in indices) deleteBookmark(tmpBookmarks[index])
} }
.show() .show()
true
} }
.show() .show()
true true
} }
R.id.published -> { R.id.published -> {
TelegraphApi.getPageList(accessToken()) { success, pageList, error -> TelegraphApi.getPageList(accessToken) { success, pageList, error ->
if (success && pageList != null && pageList.pages != null) { if (success && pageList != null && pageList.pages != null) {
MaterialDialog.Builder(this) MaterialDialog(this@MainActivity)
.title(R.string.published) .title(R.string.published)
.positiveText(android.R.string.ok) .positiveButton(R.string.open)
.items(pageList.pages.map { it.title }) .negativeButton(android.R.string.cancel)
.itemsCallback { _, _, i, _ -> .listItemsSingleChoice(items = pageList.pages.map { it.title }) { _, i, _ ->
loadPage(pageList.pages[i].path) loadPage(pageList.pages[i].path)
} }
.show() .show()
@ -282,11 +277,13 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserD
true true
} }
R.id.bookmark -> { R.id.bookmark -> {
MaterialDialog.Builder(this) MaterialDialog(this@MainActivity)
.title(R.string.title_question) .title(R.string.title_question)
.input(getString(R.string.title_hint), "", { _, input -> .input(hintRes = R.string.title_hint, prefill = currentPage?.title
addBookmark(currentUrl.split("/").last(), input.toString()) ?: "", allowEmpty = false) { _, input ->
}) val curPage = currentPage
if (curPage?.url != null) addBookmark(curPage.url.split("/").last(), input.toString())
}
.show() .show()
true true
} }
@ -294,25 +291,28 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener, FileChooserD
val shareIntent = Intent() val shareIntent = Intent()
shareIntent.action = Intent.ACTION_SEND shareIntent.action = Intent.ACTION_SEND
shareIntent.type = "text/plain" shareIntent.type = "text/plain"
shareIntent.putExtra(Intent.EXTRA_TITLE, webView?.title) shareIntent.putExtra(Intent.EXTRA_TITLE, currentPage?.title)
shareIntent.putExtra(Intent.EXTRA_TEXT, currentUrl) shareIntent.putExtra(Intent.EXTRA_TEXT, currentPage?.url)
startActivity(Intent.createChooser(shareIntent, getString(R.string.share))) startActivity(Intent.createChooser(shareIntent, getString(R.string.share)))
true true
} }
R.id.help -> { R.id.about -> {
MaterialDialog.Builder(this) val aboutIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/jlelse/teleposter"))
.title(R.string.help) startActivity(aboutIntent)
.content(R.string.help_text, true) true
.positiveText(android.R.string.ok) }
R.id.login -> {
MaterialDialog(this@MainActivity)
.title(R.string.login)
.message(R.string.login_desc)
.positiveButton(android.R.string.ok)
.positiveButton {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/telegraph")))
}
.show() .show()
true true
} }
else -> super.onOptionsItemSelected(item) else -> super.onOptionsItemSelected(item)
} }
} }
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
}
} }

View File

@ -1,7 +1,7 @@
package telegra.ph package telegra.ph
import android.content.Context import android.content.Context
import android.preference.PreferenceManager import androidx.preference.PreferenceManager
const val listItemSeparator = "+++;+++" const val listItemSeparator = "+++;+++"
const val itemSeparator = "xxx;xxx" const val itemSeparator = "xxx;xxx"
@ -29,14 +29,14 @@ fun Context.saveBookmarks(bookmarks: List<Pair<String, String>>) {
).apply() ).apply()
} }
fun Context.accessToken(): String = PreferenceManager.getDefaultSharedPreferences(this).getString("accessToken", "") var Context.accessToken: String
get() = PreferenceManager.getDefaultSharedPreferences(this).getString("accessToken", "") as String
set(value) {
PreferenceManager.getDefaultSharedPreferences(this).edit().putString("accessToken", value).apply()
}
fun Context.saveAccessToken(token: String) { var Context.authorName: String?
PreferenceManager.getDefaultSharedPreferences(this).edit().putString("accessToken", token).apply() get() = PreferenceManager.getDefaultSharedPreferences(this).getString("authorName", null)
} set(value) {
PreferenceManager.getDefaultSharedPreferences(this).edit().putString("authorName", value).apply()
fun Context.authorName(): String? = PreferenceManager.getDefaultSharedPreferences(this).getString("authorName", null) }
fun Context.saveAuthorName(name: String) {
PreferenceManager.getDefaultSharedPreferences(this).edit().putString("authorName", name).apply()
}

View File

@ -1,30 +1,41 @@
package telegra.ph package telegra.ph
import com.github.kittinunf.fuel.android.core.Json import com.github.kittinunf.fuel.core.FuelError
import com.github.kittinunf.fuel.android.extension.responseJson import com.github.kittinunf.fuel.core.FuelManager
import com.github.kittinunf.fuel.core.* import com.github.kittinunf.fuel.core.Request
import com.github.kittinunf.fuel.core.Response
import com.github.kittinunf.fuel.core.interceptors.redirectResponseInterceptor
import com.github.kittinunf.fuel.httpPost import com.github.kittinunf.fuel.httpPost
import com.github.kittinunf.fuel.httpUpload import com.github.kittinunf.fuel.json.FuelJson
import com.github.kittinunf.fuel.json.responseJson
import com.github.kittinunf.result.Result import com.github.kittinunf.result.Result
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import java.io.File import java.net.HttpCookie
import java.net.URLConnection
object TelegraphApi { object TelegraphApi {
// Telegraph private var loginAccessToken: String? = null
init { init {
FuelManager.instance.basePath = "https://api.telegra.ph" FuelManager.instance.basePath = "https://api.telegra.ph"
FuelManager.instance.removeAllResponseInterceptors()
FuelManager.instance.addResponseInterceptor {
telegraphLoginInterceptor()
}
// Fix login
FuelManager.instance.addResponseInterceptor {
redirectResponseInterceptor(FuelManager.instance)
it
}
} }
private fun callService(method: String, parameters: List<Pair<String, Any?>>, handler: (Request, Response, Result<Json, FuelError>) -> Unit) { private fun callService(method: String, parameters: List<Pair<String, Any?>>, handler: (Request, Response, Result<FuelJson, FuelError>) -> Unit) {
val requestObject = JSONObject() val requestObject = JSONObject()
parameters.forEach { parameters.forEach {
requestObject.put(it.first, it.second) requestObject.put(it.first, it.second)
} }
method.httpPost().header("Content-Type" to "application/json").body(requestObject.toString()).responseJson(handler) method.httpPost().header(mapOf("Content-Type" to "application/json")).body(requestObject.toString()).responseJson(handler)
} }
fun createAccount(shortName: String, authorName: String? = null, authorUrl: String? = null, callback: (success: Boolean, account: Account?, error: String?) -> Unit) { fun createAccount(shortName: String, authorName: String? = null, authorUrl: String? = null, callback: (success: Boolean, account: Account?, error: String?) -> Unit) {
@ -102,7 +113,7 @@ object TelegraphApi {
val url: String = json.optString("url") val url: String = json.optString("url")
val title: String = json.optString("title") val title: String = json.optString("title")
val description: String = json.optString("description") val description: String = json.optString("description")
val authorName: String? = json.optString("authorName") val authorName: String? = json.optString("author_name")
val authorUrl: String? = json.optString("author_url") val authorUrl: String? = json.optString("author_url")
val imageUrl: String? = json.optString("image_url") val imageUrl: String? = json.optString("image_url")
val content: String? = json.optJSONArray("content")?.parseContent() val content: String? = json.optJSONArray("content")?.parseContent()
@ -126,6 +137,9 @@ object TelegraphApi {
if (optJSONObject(i) == null) optString(i)?.let { if (optJSONObject(i) == null) optString(i)?.let {
content += it content += it
} }
// Fix mixed content
content = content.replace("http://telegra.ph", "https://telegra.ph")
content = content.replace("http://graph.org", "https://graph.org")
} }
return content return content
} }
@ -137,7 +151,7 @@ object TelegraphApi {
// Teleposter // Teleposter
private fun <T> handleResponse(result: Result<Json, FuelError>, handler: (success: Boolean, obj: T?, error: String?) -> Unit, callback: (obj: JSONObject) -> Unit) { private fun <T> handleResponse(result: Result<FuelJson, FuelError>, handler: (success: Boolean, obj: T?, error: String?) -> Unit, callback: (obj: JSONObject) -> Unit) {
val (json, error) = result val (json, error) = result
if (error == null && json != null) { if (error == null && json != null) {
val jsonObj = json.obj() val jsonObj = json.obj()
@ -151,25 +165,27 @@ object TelegraphApi {
} }
} }
fun uploadImage(file: File, callback: (success: Boolean, src: String?, error: String?) -> Unit) { // Dirty hacks
"http://telegra.ph/upload".httpUpload()
.dataParts { _, _ -> fun login(authUrl: String, callback: (success: Boolean, accessToken: String?, account: Account?) -> Unit) {
listOf(DataPart(file, name = "FileUpload", type = URLConnection.guessContentTypeFromName(file.name))) loginAccessToken = null
} authUrl.httpPost().response { _, _, _ ->
.responseJson { _, _, result -> if (loginAccessToken != null) getAccountInfo(accessToken = loginAccessToken!!) { success, account, _ ->
val (json, error) = result if (success) callback(true, loginAccessToken, account)
if (error == null && json != null) { else callback(false, null, null)
val jsonObj = json.array().optJSONObject(0) } else callback(false, null, null)
val src = jsonObj?.optString("src") }
if (src != null) {
callback(true, src, null)
} else {
callback(false, null, null)
}
} else {
callback(false, null, error?.message)
}
}
} }
private fun telegraphLoginInterceptor(): (Request, Response) -> Response =
{ _, response ->
response.headers["Set-Cookie"]
.flatMap { HttpCookie.parse(it) }
.find { it.name == "tph_token" }
?.let {
loginAccessToken = it.value
}
response
}
} }

View File

@ -0,0 +1,57 @@
package telegra.ph
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.webkit.JavascriptInterface
import im.delight.android.webview.AdvancedWebView
class Viewer @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AdvancedWebView(context, attrs, defStyleAttr) {
init {
prepare()
}
@SuppressLint("SetJavaScriptEnabled", "AddJavascriptInterface")
fun prepare() {
settings.javaScriptEnabled = true
settings.loadWithOverviewMode = true
settings.useWideViewPort = true
overScrollMode = View.OVER_SCROLL_NEVER
setMixedContentAllowed(true)
loadDataWithBaseURL("https://telegra.ph", context.assets.open("viewer.html").bufferedReader().readText(), "text/html", "utf-8", null)
}
fun showPage(page: TelegraphApi.Page) {
clearHistory()
setArticleTitle(page.title)
setAuthor(page.authorName, page.authorUrl)
setViews(page.views)
if (page.content == null) setDescription(page.description)
else setContent(page.content)
}
private fun setArticleTitle(title: String) {
this.loadUrl("javascript:setTitle('$title');")
}
private fun setAuthor(author: String?, url: String?) {
this.loadUrl("javascript:setAuthor('$author','$url');")
}
private fun setViews(views: Int) {
this.loadUrl("javascript:setViews('$views');")
}
private fun setDescription(description: String) {
this.loadUrl("javascript:setDescription('${description.replace("\n", "<br>")}');")
}
private fun setContent(content: String?) {
this.loadUrl("javascript:setContent('${content?.replace("'", "\\'")}');")
}
}

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
@ -8,14 +7,10 @@
<telegra.ph.Editor <telegra.ph.Editor
android:id="@+id/editor" android:id="@+id/editor"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"/> android:layout_height="match_parent" />
<im.delight.android.webview.AdvancedWebView <telegra.ph.Viewer
android:id="@+id/webView" android:id="@+id/viewer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent" />
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"/>
</LinearLayout> </LinearLayout>

View File

@ -1,44 +1,48 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/image"
android:title="@string/add_image"
app:showAsAction="ifRoom" />
<item <item
android:id="@+id/create" android:id="@+id/create"
android:title="@string/create" android:title="@string/create"
app:showAsAction="ifRoom"/> app:showAsAction="ifRoom" />
<item <item
android:id="@+id/publish" android:id="@+id/publish"
android:title="@string/publish" android:title="@string/publish"
app:showAsAction="ifRoom"/> app:showAsAction="ifRoom" />
<item <item
android:id="@+id/edit" android:id="@+id/edit"
android:title="@string/edit" android:title="@string/edit"
app:showAsAction="ifRoom"/> app:showAsAction="ifRoom" />
<item <item
android:id="@+id/try_edit" android:id="@+id/try_edit"
android:title="@string/try_edit" android:title="@string/try_edit"
app:showAsAction="ifRoom"/> app:showAsAction="ifRoom" />
<item <item
android:id="@+id/bookmark" android:id="@+id/bookmark"
android:title="@string/bookmark_this" android:title="@string/bookmark_this"
app:showAsAction="ifRoom"/> app:showAsAction="never" />
<item <item
android:id="@+id/bookmarks" android:id="@+id/bookmarks"
android:title="@string/bookmarks" android:title="@string/bookmarks"
app:showAsAction="ifRoom"/> app:showAsAction="never" />
<item
android:id="@+id/delete_bookmark"
android:title="@string/delete_bookmark"
app:showAsAction="never" />
<item <item
android:id="@+id/published" android:id="@+id/published"
android:title="@string/published" android:title="@string/published"
app:showAsAction="ifRoom"/> app:showAsAction="never" />
<item <item
android:id="@+id/share" android:id="@+id/share"
android:title="@string/share" android:title="@string/share"
app:showAsAction="ifRoom"/> app:showAsAction="never" />
<item <item
android:id="@+id/help" android:id="@+id/login"
android:title="@string/help" android:title="@string/login"
app:showAsAction="ifRoom"/> app:showAsAction="never" />
<item
android:id="@+id/about"
android:title="@string/about"
app:showAsAction="never" />
</menu> </menu>

View File

@ -0,0 +1,29 @@
<resources>
<string name="app_name">Teleposter</string>
<string name="yes">Ja</string>
<string name="no">Nein</string>
<string name="share">Teilen</string>
<string name="about">Über</string>
<string name="bookmarks">Lesezeichen</string>
<string name="bookmark_this">Als Lesezeichen setzen</string>
<string name="delete_bookmark">Lesezeichen löschen</string>
<string name="create">Neu</string>
<string name="title_question">Titel?</string>
<string name="title_hint">Fantastischer Post #1</string>
<string name="delete">Löschen</string>
<string name="delete_question">Wirklich löschen?</string>
<string name="publish">Veröffentlichen</string>
<string name="edit">Bearbeiten</string>
<string name="try_edit">Versuchen zu bearbeiten</string>
<string name="error">Fehler</string>
<string name="error_desc">Etwas unerwartetes ist passiert!</string>
<string name="published">Veröffentlichte Posts</string>
<string name="name_question">Dein Name?</string>
<string name="name_hint">Fantastischer Autor</string>
<string name="login_failed">Login fehlgeschlagen. Noch einmal versuchen!</string>
<string name="success">Erfolg</string>
<string name="login_success">Erfolgreich eingeloggt!</string>
<string name="login">Login</string>
<string name="login_desc">Öffne den Telegraph Bot in Telegram, wähle \"Login as * on this device\" und wähle Teleposter.</string>
<string name="open">Öffnen</string>
</resources>

View File

@ -0,0 +1,29 @@
<resources>
<string name="app_name">Teleposter</string>
<string name="yes"></string>
<string name="no">No</string>
<string name="share">Compartir</string>
<string name="about">Acerca de</string>
<string name="bookmarks">Favoritos</string>
<string name="bookmark_this">Añadir a favoritos</string>
<string name="delete_bookmark">Borrar favorito</string>
<string name="create">Nueva</string>
<string name="title_question">¿Título?</string>
<string name="title_hint">Entrada increíble #1</string>
<string name="delete">Borrar</string>
<string name="delete_question">¿Realmente quiere eliminar esto?</string>
<string name="publish">Publicar</string>
<string name="edit">Editar</string>
<string name="try_edit">Prueba a editar.</string>
<string name="error">Error</string>
<string name="error_desc">¡Pasó algo inesperado!</string>
<string name="published">Entradas publicadas</string>
<string name="name_question">¿Su nombre?</string>
<string name="name_hint">Awesome Writer</string>
<string name="login_failed">Login fallido. ¡Inténtelo de nuevo!</string>
<string name="success">Hecho</string>
<string name="login_success">¡Login realizado correctamente!</string>
<string name="login">Login</string>
<string name="login_desc">Abre el bot de Telegraph en Telegram, elija \"Login as * on this device\" y seleccione Teleposter.</string>
<string name="open">Abrir</string>
</resources>

View File

@ -0,0 +1,29 @@
<resources>
<string name="app_name">Teleposter</string>
<string name="yes">да</string>
<string name="no">Нет</string>
<string name="share">Поделиться</string>
<string name="about">Информация</string>
<string name="bookmarks">Закладки</string>
<string name="bookmark_this">Добавить в закладки</string>
<string name="delete_bookmark">Удалить закладку</string>
<string name="create">Новый</string>
<string name="title_question">Заглавие?</string>
<string name="title_hint">Крутой пост #1</string>
<string name="delete">Удалить</string>
<string name="delete_question">Вы действительно хотите удалить это?</string>
<string name="publish">Публикация</string>
<string name="edit">Изменить</string>
<string name="try_edit">Повторить изменение</string>
<string name="error">Ошибка</string>
<string name="error_desc">Случилось что-то неожиданное!</string>
<string name="published">Опубликованные посты</string>
<string name="name_question">Ваше имя?</string>
<string name="name_hint">Крутой писатель</string>
<string name="login_failed">Неудачный вход. Попробуй еще раз!</string>
<string name="success">Готово</string>
<string name="login_success">Вы успешно вошли!</string>
<string name="login">Вход</string>
<string name="login_desc">Откройте Telegraph bot в Telegram, выберите \"Login as * on this device\" и выберите Teleposter.</string>
<string name="open">Открыть</string>
</resources>

View File

@ -0,0 +1,29 @@
<resources>
<string name="app_name">Teleposter</string>
<string name="yes">Evet</string>
<string name="no">Hayır</string>
<string name="share">Paylaş</string>
<string name="about">Hakkında</string>
<string name="bookmarks">Yer imleri</string>
<string name="bookmark_this">Buna yer işareti koy</string>
<string name="delete_bookmark">Yer işaretini sil</string>
<string name="create">Yeni</string>
<string name="title_question">Başlık?</string>
<string name="title_hint">Harika mesaj #1</string>
<string name="delete">Sil</string>
<string name="delete_question">Bunu gerçekten silmek istiyor musun?</string>
<string name="publish">Yayınla</string>
<string name="edit">Düzenle</string>
<string name="try_edit">Düzenlemeye çalış</string>
<string name="error">Hata</string>
<string name="error_desc">Beklenmedik bir şey oldu!</string>
<string name="published">Mesaj yayınlandı</string>
<string name="name_question">Adınız?</string>
<string name="name_hint">Süper yazar</string>
<string name="login_failed">Giriş başarısız. Tekrar deneyin!</string>
<string name="success">Başarılı</string>
<string name="login_success">Başarıyla giriş yaptınız!</string>
<string name="login">Giriş</string>
<string name="login_desc">Telegram\'da Telegraph botunu açın, \"Login as * on this device\" seçeneğini ve Teleposter\'ı seçin.</string>
<string name="open"></string>
</resources>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="colorPrimary">#3F51B5</color> <color name="primaryColor">#fafafa</color>
<color name="colorPrimaryDark">#303F9F</color> <color name="primaryDarkColor">#c7c7c7</color>
<color name="colorAccent">#FF4081</color> <color name="primaryTextColor">#000000</color>
</resources> </resources>

View File

@ -1,29 +1,29 @@
<resources> <resources>
<string name="app_name">Teleposter</string> <string name="app_name">Teleposter</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="share">Share</string> <string name="share">Share</string>
<string name="help">Help</string> <string name="about">About</string>
<string name="help_text">
<![CDATA[<h3>Why can\'t I select headings?</h3>Unfortunately I wasn\'t able to add the feature yet, but you can do it manually via the code editor.<h3>Why can\'t I login with my Telegram account?</h3>That\'s not possible!<h3>Used libraries</h3><a href=\"https://github.com/afollestad/material-dialogs\">Material Dialogs</a>, <a href=\"https://github.com/kittinunf/Fuel\">Fuel</a>, <a href=\"https://github.com/delight-im/Android-AdvancedWebView\">AdvancedWebView</a>, <a href=\"https://github.com/googlesamples/easypermissions\">EasyPermissions</a><h3>About</h3>This app is made by <a href="https://jlelse.me">Jan-Lukas Else</a> and it\'s code is published on <a href="https://github.com/jlelse/teleposter">Github</a>.]]></string>
<string name="bookmarks">Bookmarks</string> <string name="bookmarks">Bookmarks</string>
<string name="bookmark_this">Bookmark this</string> <string name="bookmark_this">Bookmark this</string>
<string name="create">Create</string> <string name="delete_bookmark">Delete Bookmark</string>
<string name="create">New</string>
<string name="title_question">Title?</string> <string name="title_question">Title?</string>
<string name="title_hint">Awesome Post #1</string> <string name="title_hint">Awesome Post #1</string>
<string name="delete">Delete</string> <string name="delete">Delete</string>
<string name="delete_question">Do you really want to delete this?</string> <string name="delete_question">Do you really want to delete this?</string>
<string name="publish">Publish</string> <string name="publish">Publish</string>
<string name="edit">Edit (safe)</string> <string name="edit">Edit</string>
<string name="try_edit">Edit (unsafe)</string> <string name="try_edit">Try to edit</string>
<string name="error">Error</string> <string name="error">Error</string>
<string name="error_desc">Something unexpected happened!</string> <string name="error_desc">Something unexpected happened!</string>
<string name="viewer_html_head">
<![CDATA[<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css\"><style> * { max-width: 100%; height: auto; word-break: break-all; word-break: break-word; }</style><script src=\"http://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js\"></script><script src=\"https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js\"></script></head><body>]]>
</string>
<string name="viewer_html_end">
<![CDATA[</body></html>]]>
</string>
<string name="published">Published posts</string> <string name="published">Published posts</string>
<string name="name_question">Your name?</string> <string name="name_question">Your name?</string>
<string name="name_hint">Awesome Writer</string> <string name="name_hint">Awesome Writer</string>
<string name="add_image">Add image</string> <string name="login_failed">Login failed. Try again!</string>
<string name="success">Success</string>
<string name="login_success">You successfully logged in!</string>
<string name="login">Login</string>
<string name="login_desc">Open the Telegraph bot in Telegram, select \"Login as * on this device\" and choose Teleposter.</string>
<string name="open">Open</string>
</resources> </resources>

View File

@ -1,10 +1,10 @@
<resources> <resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <style name="AppTheme" parent="Theme.AppCompat.Light">
<item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimary">@color/primaryColor</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorPrimaryDark">@color/primaryDarkColor</item>
<item name="colorAccent">@color/colorAccent</item> <item name="android:textColorPrimary">@color/primaryTextColor</item>
<item name="android:colorBackground">@android:color/white</item> <item name="md_color_button_text">@color/primaryTextColor</item>
</style> </style>
</resources> </resources>

View File

@ -1,18 +1,18 @@
buildscript { buildscript {
ext.kotlin_version = '1.2.21' ext.kotlin_version = '1.4.10'
repositories { repositories {
jcenter() jcenter()
mavenCentral() mavenCentral()
google() google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.0.1' classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }
} }
plugins { plugins {
id 'com.github.ben-manes.versions' version '0.17.0' id 'com.github.ben-manes.versions' version '0.33.0'
} }
allprojects { allprojects {

View File

@ -1,6 +1,6 @@
kotlin.incremental=true kotlin.incremental=true
org.gradle.parallel=true org.gradle.parallel=true
org.gradle.configureondemand=true
org.gradle.jvmargs=-Xmx3072M org.gradle.jvmargs=-Xmx3072M
android.enableD8=true android.enableD8=true
android.enableAapt2=false android.useAndroidX=true
android.enableJetifier=true

Binary file not shown.

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-bin.zip

53
gradlew vendored
View File

@ -1,5 +1,21 @@
#!/usr/bin/env sh #!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# 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
#
# https://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.
#
############################################################################## ##############################################################################
## ##
## Gradle start up script for UN*X ## Gradle start up script for UN*X
@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"` APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS="" DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD="maximum"
@ -66,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@ -109,10 +126,11 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi fi
# For Cygwin, switch paths to Windows format before running java # For Cygwin or MSYS, switch paths to Windows format before running java
if $cygwin ; then if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"` JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath # We build the pattern for arguments to be converted via cygpath
@ -138,19 +156,19 @@ if $cygwin ; then
else else
eval `echo args$i`="\"$arg\"" eval `echo args$i`="\"$arg\""
fi fi
i=$((i+1)) i=`expr $i + 1`
done done
case $i in case $i in
(0) set -- ;; 0) set -- ;;
(1) set -- "$args0" ;; 1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;; 2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;; 3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;; 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac esac
fi fi
@ -159,14 +177,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " " echo " "
} }
APP_ARGS=$(save "$@") APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules # Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@" exec "$JAVACMD" "$@"

43
gradlew.bat vendored
View File

@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off @if "%DEBUG%" == "" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS= set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init if "%ERRORLEVEL%" == "0" goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -35,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init if exist "%JAVA_EXE%" goto execute
echo. echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@ -45,28 +64,14 @@ echo location of your Java installation.
goto fail goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell