Add likes and better authentication
This commit is contained in:
parent
f2afb939c6
commit
1d92436a3c
|
@ -6,8 +6,8 @@ android {
|
|||
applicationId "eu.stuifzand.micropub"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 26
|
||||
versionCode 5
|
||||
versionName '0.0.5-alpha'
|
||||
versionCode 7
|
||||
versionName '0.0.7-alpha'
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
android:name="android.permission.GET_ACCOUNTS"
|
||||
android:maxSdkVersion="22" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.MANAGE_ACCOUNTS"
|
||||
android:maxSdkVersion="22" />
|
||||
|
@ -34,12 +33,18 @@
|
|||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<data android:mimeType="text/plain"/>
|
||||
<data android:mimeType="image/*"/>
|
||||
<action android:name="android.intent.action.VIEW"></action>
|
||||
<category android:name="android.intent.category.DEFAULT"></category>
|
||||
<category android:name="android.intent.category.BROWSABLE"></category>
|
||||
<data android:scheme="wrimini"></data>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<data android:mimeType="text/plain" />
|
||||
<data android:mimeType="image/*" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".auth.WebSigninActivity" />
|
||||
|
@ -56,9 +61,17 @@
|
|||
|
||||
<meta-data
|
||||
android:name="android.accounts.AccountAuthenticator"
|
||||
android:resource="@xml/authenticator" /> <!-- We haven't defined this -->
|
||||
android:resource="@xml/authenticator" />
|
||||
</service>
|
||||
|
||||
<activity android:name=".LikeActivity">
|
||||
<intent-filter android:label="@string/like">
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
|
||||
|
||||
</manifest>
|
5
app/src/main/java/eu/stuifzand/micropub/AuthError.java
Normal file
5
app/src/main/java/eu/stuifzand/micropub/AuthError.java
Normal file
|
@ -0,0 +1,5 @@
|
|||
package eu.stuifzand.micropub;
|
||||
|
||||
interface AuthError {
|
||||
void handleErrorMessage(String msg);
|
||||
}
|
180
app/src/main/java/eu/stuifzand/micropub/LikeActivity.java
Normal file
180
app/src/main/java/eu/stuifzand/micropub/LikeActivity.java
Normal file
|
@ -0,0 +1,180 @@
|
|||
package eu.stuifzand.micropub;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.databinding.DataBindingUtil;
|
||||
import android.net.Uri;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import eu.stuifzand.micropub.client.Client;
|
||||
import eu.stuifzand.micropub.client.Post;
|
||||
import eu.stuifzand.micropub.databinding.ActivityLikeBinding;
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
public class LikeActivity extends AppCompatActivity {
|
||||
|
||||
private AccountManager accountManager;
|
||||
|
||||
private Account selectedAccount;
|
||||
private String authToken;
|
||||
private Client client;
|
||||
private PostViewModel postModel;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
accountManager = AccountManager.get(this);
|
||||
|
||||
AccountManager am = AccountManager.get(this);
|
||||
Bundle options = new Bundle();
|
||||
|
||||
postModel = ViewModelProviders.of(LikeActivity.this).get(PostViewModel.class);
|
||||
client = ViewModelProviders.of(LikeActivity.this).get(Client.class);
|
||||
|
||||
TokenReady callback = (accountType, accountName, token) -> {
|
||||
Account[] accounts = accountManager.getAccountsByType(accountType);
|
||||
if (accounts.length == 0)
|
||||
return;
|
||||
selectedAccount = accounts[0];
|
||||
authToken = token;
|
||||
|
||||
String micropubBackend = accountManager.getUserData(selectedAccount, "micropub");
|
||||
if (micropubBackend == null) return;
|
||||
|
||||
client.setToken(accountType, accountName, token);
|
||||
client.loadConfig(HttpUrl.parse(micropubBackend));
|
||||
|
||||
final View coordinator = findViewById(R.id.coordinator);
|
||||
|
||||
client.getResponse().observe(LikeActivity.this, response -> {
|
||||
Log.i("micropub", "response received " + response.isSuccess());
|
||||
if (response.isSuccess()) {
|
||||
postModel.clear();
|
||||
Snackbar.make(coordinator, R.string.post_successful, Snackbar.LENGTH_LONG)
|
||||
.setAction("Open", v -> {
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(response.getUrl()));
|
||||
startActivity(browserIntent);
|
||||
})
|
||||
.show();
|
||||
} else {
|
||||
Snackbar.make(coordinator, R.string.post_failed, Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
client.getMediaResponse().observe(LikeActivity.this, response -> {
|
||||
Log.i("micropub", "media response received " + response.isSuccess());
|
||||
if (response.isSuccess()) {
|
||||
postModel.setPhoto(response.getUrl());
|
||||
Toast.makeText(LikeActivity.this, "Photo upload succesful, photo url filled", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
AuthError onError = (msg) -> {
|
||||
LikeActivity.this.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
Toast.makeText(LikeActivity.this, msg, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
};
|
||||
accountManager.getAuthTokenByFeatures(
|
||||
"Indieauth",
|
||||
"token",
|
||||
null,
|
||||
this,
|
||||
options,
|
||||
null,
|
||||
new OnTokenAcquired(this, callback, onError),
|
||||
null
|
||||
);
|
||||
|
||||
// setContentView(R.layout.activity_main);
|
||||
ActivityLikeBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_like);
|
||||
|
||||
binding.setViewModel(postModel);
|
||||
binding.setClient(client);
|
||||
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
|
||||
|
||||
Intent intent = getIntent();
|
||||
Log.i("micropub", intent.toString());
|
||||
if (intent != null) {
|
||||
String urlOrNote = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||
if (urlOrNote != null) {
|
||||
HttpUrl url = HttpUrl.parse(urlOrNote);
|
||||
if (url != null) {
|
||||
postModel.likeOf.set(urlOrNote);
|
||||
} else {
|
||||
postModel.findLikeOf(urlOrNote);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.menu_like, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
int id = item.getItemId();
|
||||
|
||||
//noinspection SimplifiableIfStatement
|
||||
if (id == R.id.action_send) {
|
||||
InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
if (this.getCurrentFocus() != null && inputManager != null) {
|
||||
inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0);
|
||||
inputManager.hideSoftInputFromInputMethod(this.getCurrentFocus().getWindowToken(), 0);
|
||||
}
|
||||
sendPost(null);
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
public void sendPost(View view) {
|
||||
AccountManager am = AccountManager.get(this);
|
||||
Bundle options = new Bundle();
|
||||
|
||||
TokenReady callback = (accountType, accountName, token) -> {
|
||||
String micropubBackend = accountManager.getUserData(selectedAccount, "micropub");
|
||||
if (micropubBackend == null) {
|
||||
Log.i("micropub", "micropub backend == null");
|
||||
return;
|
||||
}
|
||||
Log.i("micropub", "Sending message to " + micropubBackend);
|
||||
Post post = postModel.getPost();
|
||||
client.createPost(post, token, HttpUrl.parse(micropubBackend));
|
||||
};
|
||||
AuthError onError = (msg) -> {
|
||||
LikeActivity.this.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
Toast.makeText(LikeActivity.this, msg, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
accountManager.getAuthTokenByFeatures("Indieauth", "token", null, this, options, null, new OnTokenAcquired(this, callback, onError), null);
|
||||
}
|
||||
}
|
|
@ -3,10 +3,17 @@ package eu.stuifzand.micropub;
|
|||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.databinding.DataBindingUtil;
|
||||
import android.media.session.MediaSession;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
|
@ -14,6 +21,8 @@ import android.view.Menu;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
@ -60,10 +69,20 @@ public class MainActivity extends AppCompatActivity {
|
|||
client.setToken(accountType, accountName, token);
|
||||
client.loadConfig(HttpUrl.parse(micropubBackend));
|
||||
|
||||
final View coordinator = findViewById(R.id.coordinator);
|
||||
|
||||
client.getResponse().observe(MainActivity.this, response -> {
|
||||
Log.i("micropub", "response received " + response.isSuccess());
|
||||
if (response.isSuccess()) {
|
||||
postModel.clear();
|
||||
Snackbar.make(coordinator, R.string.post_successful, Snackbar.LENGTH_LONG)
|
||||
.setAction("Open", v -> {
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(response.getUrl()));
|
||||
startActivity(browserIntent);
|
||||
})
|
||||
.show();
|
||||
} else {
|
||||
Snackbar.make(coordinator, R.string.post_failed, Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -71,10 +90,28 @@ public class MainActivity extends AppCompatActivity {
|
|||
Log.i("micropub", "media response received " + response.isSuccess());
|
||||
if (response.isSuccess()) {
|
||||
postModel.setPhoto(response.getUrl());
|
||||
Toast.makeText(MainActivity.this, "Photo upload succesful, photo url filled", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
};
|
||||
accountManager.getAuthTokenByFeatures("Indieauth", "token", null, this, options, null, new OnTokenAcquired(this, callback), null);
|
||||
|
||||
AuthError onError = (msg) -> {
|
||||
MainActivity.this.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
};
|
||||
accountManager.getAuthTokenByFeatures(
|
||||
"Indieauth",
|
||||
"token",
|
||||
null,
|
||||
this,
|
||||
options,
|
||||
null,
|
||||
new OnTokenAcquired(this, callback, onError),
|
||||
null
|
||||
);
|
||||
|
||||
// setContentView(R.layout.activity_main);
|
||||
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
|
||||
|
@ -93,7 +130,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
if (url != null) {
|
||||
postModel.inReplyTo.set(urlOrNote);
|
||||
} else {
|
||||
postModel.content.set(urlOrNote);
|
||||
postModel.findReplyTo(urlOrNote);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,9 +161,23 @@ public class MainActivity extends AppCompatActivity {
|
|||
|
||||
//noinspection SimplifiableIfStatement
|
||||
if (id == R.id.action_settings) {
|
||||
// TODO: implement some settings
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_send) {
|
||||
InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
if (this.getCurrentFocus() != null && inputManager != null) {
|
||||
inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0);
|
||||
inputManager.hideSoftInputFromInputMethod(this.getCurrentFocus().getWindowToken(), 0);
|
||||
}
|
||||
sendPost(null);
|
||||
} else if (id == R.id.action_photo) {
|
||||
InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
if (this.getCurrentFocus() != null && inputManager != null) {
|
||||
inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0);
|
||||
inputManager.hideSoftInputFromInputMethod(this.getCurrentFocus().getWindowToken(), 0);
|
||||
}
|
||||
galleryIntent(null);
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
|
@ -146,8 +197,15 @@ public class MainActivity extends AppCompatActivity {
|
|||
Post post = postModel.getPost();
|
||||
client.createPost(post, token, HttpUrl.parse(micropubBackend));
|
||||
};
|
||||
AuthError onError = (msg) -> {
|
||||
MainActivity.this.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
accountManager.getAuthTokenByFeatures("Indieauth", "token", null, this, options, null, new OnTokenAcquired(this, callback), null);
|
||||
accountManager.getAuthTokenByFeatures("Indieauth", "token", null, this, options, null, new OnTokenAcquired(this, callback, onError), null);
|
||||
}
|
||||
|
||||
public void galleryIntent(View view) {
|
||||
|
@ -179,8 +237,10 @@ public class MainActivity extends AppCompatActivity {
|
|||
|
||||
client.postMedia(output, mimeType);
|
||||
} catch (FileNotFoundException e) {
|
||||
Toast.makeText(this, "File not found: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
Log.e("micropub", "Error while copying image", e);
|
||||
} catch (IOException e) {
|
||||
Toast.makeText(this, "Problem with IO " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
Log.e("micropub", "Error while copying image", e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,18 +7,22 @@ import android.accounts.AuthenticatorException;
|
|||
import android.accounts.OperationCanceledException;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class OnTokenAcquired implements AccountManagerCallback<Bundle> {
|
||||
private final TokenReady callback;
|
||||
private AuthError error;
|
||||
private Activity activity;
|
||||
|
||||
public OnTokenAcquired(Activity activity, TokenReady callback) {
|
||||
public OnTokenAcquired(Activity activity, TokenReady callback, AuthError error) {
|
||||
this.activity = activity;
|
||||
this.callback = callback;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -39,10 +43,13 @@ public class OnTokenAcquired implements AccountManagerCallback<Bundle> {
|
|||
callback.tokenReady(bundle.getString("accountType"), bundle.getString("authAccount"), token);
|
||||
} catch (OperationCanceledException e) {
|
||||
Log.e("micropub", "on token acquired", e);
|
||||
error.handleErrorMessage(e.getMessage());
|
||||
} catch (IOException e) {
|
||||
Log.e("micropub", "on token acquired", e);
|
||||
error.handleErrorMessage(e.getMessage());
|
||||
} catch (AuthenticatorException e) {
|
||||
Log.e("micropub", "on token acquired", e);
|
||||
error.handleErrorMessage(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import android.databinding.ObservableField;
|
|||
import android.databinding.ObservableList;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import eu.stuifzand.micropub.client.Client;
|
||||
import eu.stuifzand.micropub.client.Post;
|
||||
|
@ -13,11 +15,18 @@ import eu.stuifzand.micropub.client.Syndication;
|
|||
import okhttp3.HttpUrl;
|
||||
|
||||
public class PostViewModel extends ViewModel {
|
||||
private static final Pattern urlPattern = Pattern.compile(
|
||||
"(?:^|[\\W])((ht|f)tp(s?):\\/\\/|www\\.)"
|
||||
+ "(([\\w\\-]+\\.){1,}?([\\w\\-.~]+\\/?)*"
|
||||
+ "[\\p{Alnum}.,%_=?&#\\-+()\\[\\]\\*$~@!:/{};']*)",
|
||||
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
||||
|
||||
public final ObservableField<String> name = new ObservableField<>();
|
||||
public final ObservableField<String> content = new ObservableField<>();
|
||||
public final ObservableField<String> category = new ObservableField<>();
|
||||
public final ObservableField<String> inReplyTo = new ObservableField<>();
|
||||
public final ObservableField<String> photo = new ObservableField<>();
|
||||
public final ObservableField<String> likeOf = new ObservableField<>();
|
||||
|
||||
public PostViewModel() {
|
||||
this.name.set("");
|
||||
|
@ -25,6 +34,7 @@ public class PostViewModel extends ViewModel {
|
|||
this.category.set("");
|
||||
this.inReplyTo.set("");
|
||||
this.photo.set("");
|
||||
this.likeOf.set("");
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
|
@ -33,6 +43,26 @@ public class PostViewModel extends ViewModel {
|
|||
this.category.set("");
|
||||
this.inReplyTo.set("");
|
||||
this.photo.set("");
|
||||
this.likeOf.set("");
|
||||
}
|
||||
|
||||
public void findReplyTo(String urlOrNote) {
|
||||
Matcher matcher = urlPattern.matcher(urlOrNote);
|
||||
if (matcher.find()) {
|
||||
String url = matcher.group(1);
|
||||
inReplyTo.set(url);
|
||||
String s = urlOrNote.replaceFirst(urlPattern.pattern(), "");
|
||||
this.content.set(s);
|
||||
} else {
|
||||
this.content.set(urlOrNote);
|
||||
}
|
||||
}
|
||||
|
||||
public void findLikeOf(String urlOrNote) {
|
||||
Matcher matcher = urlPattern.matcher(urlOrNote);
|
||||
if (matcher.find()) {
|
||||
likeOf.set(matcher.group(1));
|
||||
}
|
||||
}
|
||||
|
||||
public void setPhoto(String url) {
|
||||
|
@ -44,6 +74,7 @@ public class PostViewModel extends ViewModel {
|
|||
if (!this.photo.get().equals("")) {
|
||||
post.setPhoto(this.photo.get());
|
||||
}
|
||||
post.setLikeOf(HttpUrl.parse(likeOf.get()));
|
||||
return post;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.accounts.AccountAuthenticatorActivity;
|
|||
import android.accounts.AccountAuthenticatorResponse;
|
||||
import android.accounts.AccountManager;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.RequiresApi;
|
||||
|
@ -15,6 +16,8 @@ import android.webkit.WebSettings;
|
|||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import eu.stuifzand.micropub.R;
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
|
@ -37,7 +40,6 @@ public class AuthenticationActivity extends AccountAuthenticatorActivity {
|
|||
final String me = intent.getStringExtra(WebsigninTask.ME);
|
||||
final AccountAuthenticatorResponse response = intent.getParcelableExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE);
|
||||
|
||||
|
||||
WebView webview = findViewById(R.id.webview);
|
||||
WebSettings webSettings = webview.getSettings();
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
|
@ -46,7 +48,7 @@ public class AuthenticationActivity extends AccountAuthenticatorActivity {
|
|||
HttpUrl.Builder builder = HttpUrl.parse(endpoint).newBuilder();
|
||||
builder.setQueryParameter("me", me)
|
||||
.setQueryParameter("client_id", "https://stuifzand.eu/micropub")
|
||||
.setQueryParameter("redirect_uri", "https://stuifzand.eu/micropub-auth")
|
||||
.setQueryParameter("redirect_uri", "wrimini://oauth")
|
||||
.setQueryParameter("response_type", "code")
|
||||
.setQueryParameter("state", "1234") // @TODO use random states, check the state later
|
||||
.setQueryParameter("scope", "create edit update post delete"); // @TODO use different scope
|
||||
|
@ -56,7 +58,7 @@ public class AuthenticationActivity extends AccountAuthenticatorActivity {
|
|||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
|
||||
Log.i("micropub", request.getMethod()+ " "+request.getUrl());
|
||||
Log.i("micropub", request.getMethod() + " " + request.getUrl());
|
||||
Log.i("micropub", error.toString());
|
||||
}
|
||||
|
||||
|
@ -64,10 +66,10 @@ public class AuthenticationActivity extends AccountAuthenticatorActivity {
|
|||
public boolean shouldOverrideUrlLoading(WebView viewx, WebResourceRequest request) {
|
||||
Log.i("micropub", "New API: " + request.getUrl().toString());
|
||||
String url = request.getUrl().toString();
|
||||
if (url.startsWith("https://stuifzand.eu/micropub-auth")) {
|
||||
HttpUrl httpUrl = HttpUrl.parse(url);
|
||||
String code = httpUrl.queryParameter("code");
|
||||
String state = httpUrl.queryParameter("state");
|
||||
if (url.startsWith("wrimini://oauth")) {
|
||||
Uri uri = Uri.parse(url);
|
||||
String code = uri.getQueryParameter("code");
|
||||
//String state = httpUrl.queryParameter("state");
|
||||
|
||||
new VerifyAuthenticationTask(response, AuthenticationActivity.this).execute(endpoint, me, code);
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ public class Authenticator extends AbstractAccountAuthenticator {
|
|||
if (TextUtils.isEmpty(authToken)) {
|
||||
RequestBody formBody = new FormBody.Builder()
|
||||
.add("code", am.getPassword(account))
|
||||
.add("redirect_uri", "https://stuifzand.eu/micropub-auth")
|
||||
.add("redirect_uri", "wrimini://oauth")
|
||||
.add("client_id", "https://stuifzand.eu/micropub")
|
||||
.add("me", account.name)
|
||||
.add("grant_type", "authorization_code")
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package eu.stuifzand.micropub.auth;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountAuthenticatorResponse;
|
||||
import android.accounts.AccountManager;
|
||||
import android.content.Intent;
|
||||
|
@ -70,7 +71,7 @@ public class VerifyAuthenticationTask extends AsyncTask<String, Void, VerifyAuth
|
|||
|
||||
RequestBody formBody = new FormBody.Builder()
|
||||
.add("code", code)
|
||||
.add("redirect_uri", "https://stuifzand.eu/micropub-auth")
|
||||
.add("redirect_uri", "wrimini://oauth")
|
||||
.add("client_id", "https://stuifzand.eu/micropub")
|
||||
.build();
|
||||
|
||||
|
@ -141,7 +142,7 @@ public class VerifyAuthenticationTask extends AsyncTask<String, Void, VerifyAuth
|
|||
this.activity.finishLogin(intent);
|
||||
this.response.onResult(bundle);
|
||||
} else {
|
||||
this.response.onError(1, "Could not verify authorization: " + message.getErrorMessage());
|
||||
this.response.onError(AccountManager.ERROR_CODE_BAD_AUTHENTICATION, "Could not verify authorization: " + message.getErrorMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.content.Intent;
|
|||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.jsoup.Connection;
|
||||
import org.jsoup.Jsoup;
|
||||
|
@ -49,6 +50,7 @@ public class WebsigninTask extends AsyncTask<String, Void, Bundle> {
|
|||
String profileUrl = strings[0];
|
||||
bundle.putString(ME, profileUrl);
|
||||
Connection conn = Jsoup.connect(profileUrl);
|
||||
conn.timeout(10*1000);
|
||||
Document doc = conn.get();
|
||||
Connection.Response resp = conn.response();
|
||||
|
||||
|
@ -81,7 +83,8 @@ public class WebsigninTask extends AsyncTask<String, Void, Bundle> {
|
|||
linkHeaders.put(rel, link.attr("href"));
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
} catch (Exception e) {
|
||||
bundle.putString("ERROR", e.getMessage());
|
||||
return bundle;
|
||||
}
|
||||
|
||||
|
@ -93,12 +96,23 @@ public class WebsigninTask extends AsyncTask<String, Void, Bundle> {
|
|||
}
|
||||
}
|
||||
|
||||
for (String rel : rels) {
|
||||
if (bundle.getString(rel) == null) {
|
||||
bundle.putString("ERROR", "Missing header or link: " + rel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Log.i("micropub", bundle.toString());
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Bundle bundle) {
|
||||
String error = bundle.getString("ERROR");
|
||||
if (error != null && error.length() > 0) {
|
||||
Toast.makeText(this.activity, error, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent(this.activity, AuthenticationActivity.class);
|
||||
intent.putExtras(activity.getIntent());
|
||||
intent.putExtras(bundle);
|
||||
|
|
|
@ -9,23 +9,27 @@ public class Post {
|
|||
private String[] categories;
|
||||
private String[] syndicationUids;
|
||||
private String photo;
|
||||
private HttpUrl likeOf;
|
||||
|
||||
public Post(String content) {
|
||||
this.content = content;
|
||||
if (content.equals("")) {
|
||||
this.content=null;
|
||||
} else {
|
||||
this.content = content;
|
||||
}
|
||||
this.categories = new String[]{};
|
||||
this.syndicationUids = new String[]{};
|
||||
}
|
||||
|
||||
public Post(String name, String content) {
|
||||
this.name = name;
|
||||
this.content = content;
|
||||
this(content);
|
||||
this.categories = new String[]{};
|
||||
this.name = name;
|
||||
this.syndicationUids = new String[]{};
|
||||
}
|
||||
|
||||
public Post(String name, String content, String categories) {
|
||||
this.name = name;
|
||||
this.content = content;
|
||||
this(name, content);
|
||||
this.categories = categories.split("\\s+");
|
||||
if (this.categories.length == 1 && this.categories[0].length() == 0) {
|
||||
this.categories = new String[]{};
|
||||
|
@ -82,4 +86,20 @@ public class Post {
|
|||
public boolean hasPhoto() {
|
||||
return this.photo != null;
|
||||
}
|
||||
|
||||
public boolean hasLikeOf() {
|
||||
return this.likeOf != null;
|
||||
}
|
||||
|
||||
public void setLikeOf(HttpUrl likeOf) {
|
||||
this.likeOf = likeOf;
|
||||
}
|
||||
|
||||
public String getLikeOf() {
|
||||
return likeOf.toString();
|
||||
}
|
||||
|
||||
public boolean hasContent() {
|
||||
return content != null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,9 +31,11 @@ class PostTask extends AsyncTask<String, Void, Void> {
|
|||
@Override
|
||||
protected Void doInBackground(String... strings) {
|
||||
FormBody.Builder builder = new FormBody.Builder();
|
||||
builder.add("h", "entry")
|
||||
.add("content", post.getContent());
|
||||
builder.add("h", "entry");
|
||||
|
||||
if (post.hasContent()) {
|
||||
builder.add("content", post.getContent());
|
||||
}
|
||||
for (String cat : post.getCategories()) {
|
||||
builder.add("category[]", cat);
|
||||
}
|
||||
|
@ -54,6 +56,10 @@ class PostTask extends AsyncTask<String, Void, Void> {
|
|||
builder.add("photo", post.getPhoto());
|
||||
}
|
||||
|
||||
if (post.hasLikeOf()) {
|
||||
builder.add("like-of", post.getLikeOf());
|
||||
}
|
||||
|
||||
RequestBody formBody = builder.build();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
|
@ -76,15 +82,16 @@ class PostTask extends AsyncTask<String, Void, Void> {
|
|||
okhttp3.Response httpResponse = null;
|
||||
try {
|
||||
httpResponse = call.execute();
|
||||
if (httpResponse.code() == 201) {
|
||||
int code = httpResponse.code();
|
||||
if (code == 201) {
|
||||
String location = httpResponse.header("Location");
|
||||
response.postValue(Response.successful(location));
|
||||
} else {
|
||||
response.postValue(Response.failed());
|
||||
response.postValue(Response.failed(httpResponse.toString()));
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
response.postValue(Response.failed());
|
||||
response.postValue(Response.failed(e.getMessage()));
|
||||
} finally {
|
||||
if (httpResponse != null) {
|
||||
httpResponse.close();
|
||||
|
|
|
@ -13,8 +13,8 @@ public class Response {
|
|||
this.url = url;
|
||||
}
|
||||
|
||||
public static Response failed() {
|
||||
return new Response(false);
|
||||
public static Response failed(String why) {
|
||||
return new Response(false, why);
|
||||
}
|
||||
|
||||
public static Response successful(String url) {
|
||||
|
@ -24,8 +24,8 @@ public class Response {
|
|||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
public String getWhy() { return url; }
|
||||
}
|
||||
|
|
46
app/src/main/res/layout/activity_like.xml
Normal file
46
app/src/main/res/layout/activity_like.xml
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="eu.stuifzand.micropub.PostViewModel" />
|
||||
|
||||
<variable
|
||||
name="client"
|
||||
type="eu.stuifzand.micropub.client.Client" />
|
||||
</data>
|
||||
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
android:id="@+id/coordinator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="eu.stuifzand.micropub.MainActivity">
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/editLikeOfTextLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/editLikeOfText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Like of"
|
||||
android:singleLine="true"
|
||||
android:text="@={viewModel.likeOf}" />
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
</layout>
|
|
@ -14,6 +14,7 @@
|
|||
</data>
|
||||
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
android:id="@+id/coordinator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="eu.stuifzand.micropub.MainActivity">
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="eu.stuifzand.micropub.PostViewModel" />
|
||||
|
@ -14,19 +13,23 @@
|
|||
type="eu.stuifzand.micropub.client.Client" />
|
||||
</data>
|
||||
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/scrollView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/colorPrimary"
|
||||
android:fillViewport="false"
|
||||
android:fillViewport="true"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
tools:context="eu.stuifzand.micropub.MainActivity"
|
||||
tools:showIn="@layout/activity_main">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
|
@ -34,8 +37,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:overScrollMode="always"
|
||||
android:paddingTop="8dp"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
android:scrollbars="vertical">
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/editInReplyToLayout"
|
||||
|
@ -62,6 +64,32 @@
|
|||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/editNameLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/in_reply_to"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/editName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56sp"
|
||||
android:ems="10"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textAutoComplete|textUri"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:nextFocusForward="@id/content"
|
||||
android:singleLine="true"
|
||||
android:text="@={viewModel.name}"
|
||||
app:layout_constraintTop_toBottomOf="@+id/editInReplyToLayout" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/contentLayout"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -71,7 +99,7 @@
|
|||
app:counterEnabled="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/editInReplyToLayout">
|
||||
app:layout_constraintTop_toBottomOf="@+id/editNameLayout">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/content"
|
||||
|
@ -134,33 +162,12 @@
|
|||
<ListView
|
||||
android:id="@+id/listSyndication"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="115dp"
|
||||
android:layout_height="69dp"
|
||||
android:isScrollContainer="false"
|
||||
app:list="@{client.syndicates}" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnPost"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:onClick="sendPost"
|
||||
android:text="@string/post"
|
||||
app:layout_constraintEnd_toEndOf="@id/editCategoryLayout"
|
||||
app:layout_constraintTop_toBottomOf="@+id/editPhotoLayout" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnGetImage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:onClick="galleryIntent"
|
||||
android:text="Select photo"
|
||||
app:layout_constraintEnd_toStartOf="@+id/btnPost"
|
||||
app:layout_constraintTop_toBottomOf="@+id/editPhotoLayout" />
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/editPhotoLayout"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -174,7 +181,7 @@
|
|||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/editPhoto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56sp"
|
||||
android:layout_height="52dp"
|
||||
android:ems="10"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="text"
|
||||
|
@ -186,6 +193,5 @@
|
|||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
</layout>
|
14
app/src/main/res/menu/menu_like.xml
Normal file
14
app/src/main/res/menu/menu_like.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="eu.stuifzand.micropub.LikeActivity">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_send"
|
||||
android:enabled="true"
|
||||
android:icon="@mipmap/ic_send_black_48dp"
|
||||
android:orderInCategory="10"
|
||||
android:title="@string/action_send"
|
||||
app:showAsAction="always" />
|
||||
|
||||
</menu>
|
|
@ -8,11 +8,20 @@
|
|||
android:title="@string/action_settings"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item android:id="@+id/action_send"
|
||||
<item
|
||||
android:id="@+id/action_photo"
|
||||
android:enabled="true"
|
||||
android:icon="@mipmap/ic_image_black_48dp"
|
||||
android:orderInCategory="10"
|
||||
android:title="Send"
|
||||
android:icon="@drawable/ic_menu_send"
|
||||
app:showAsAction="ifRoom"
|
||||
/>
|
||||
android:title="@string/action_photo"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_send"
|
||||
android:enabled="true"
|
||||
android:icon="@mipmap/ic_send_black_48dp"
|
||||
android:orderInCategory="10"
|
||||
android:title="@string/action_send"
|
||||
app:showAsAction="always" />
|
||||
|
||||
</menu>
|
BIN
app/src/main/res/mipmap-xxhdpi/ic_image_black_48dp.png
Normal file
BIN
app/src/main/res/mipmap-xxhdpi/ic_image_black_48dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 807 B |
BIN
app/src/main/res/mipmap-xxhdpi/ic_send_black_48dp.png
Normal file
BIN
app/src/main/res/mipmap-xxhdpi/ic_send_black_48dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 714 B |
|
@ -11,4 +11,10 @@
|
|||
<string name="post">Post</string>
|
||||
<string name="syndication">Syndicate to</string>
|
||||
<string name="user_agent">Wrimini</string>
|
||||
<string name="post_successful">Post successful</string>
|
||||
<string name="post_failed">Post failed</string>
|
||||
<string name="action_photo">Photo</string>
|
||||
<string name="action_send">Send</string>
|
||||
<string name="like">Like</string>
|
||||
<string name="bookmark">Bookmark</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue
Block a user