Add likes and better authentication
This commit is contained in:
parent
f2afb939c6
commit
1d92436a3c
|
@ -6,8 +6,8 @@ android {
|
||||||
applicationId "eu.stuifzand.micropub"
|
applicationId "eu.stuifzand.micropub"
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 26
|
targetSdkVersion 26
|
||||||
versionCode 5
|
versionCode 7
|
||||||
versionName '0.0.5-alpha'
|
versionName '0.0.7-alpha'
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
android:name="android.permission.GET_ACCOUNTS"
|
android:name="android.permission.GET_ACCOUNTS"
|
||||||
android:maxSdkVersion="22" />
|
android:maxSdkVersion="22" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.MANAGE_ACCOUNTS"
|
android:name="android.permission.MANAGE_ACCOUNTS"
|
||||||
android:maxSdkVersion="22" />
|
android:maxSdkVersion="22" />
|
||||||
|
@ -34,12 +33,18 @@
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEND"/>
|
<action android:name="android.intent.action.VIEW"></action>
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"></category>
|
||||||
<data android:mimeType="text/plain"/>
|
<category android:name="android.intent.category.BROWSABLE"></category>
|
||||||
<data android:mimeType="image/*"/>
|
<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>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".auth.WebSigninActivity" />
|
<activity android:name=".auth.WebSigninActivity" />
|
||||||
|
@ -56,9 +61,17 @@
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.accounts.AccountAuthenticator"
|
android:name="android.accounts.AccountAuthenticator"
|
||||||
android:resource="@xml/authenticator" /> <!-- We haven't defined this -->
|
android:resource="@xml/authenticator" />
|
||||||
</service>
|
</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>
|
</application>
|
||||||
|
|
||||||
|
|
||||||
</manifest>
|
</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.Account;
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.Notification;
|
||||||
import android.arch.lifecycle.ViewModelProviders;
|
import android.arch.lifecycle.ViewModelProviders;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.databinding.DataBindingUtil;
|
import android.databinding.DataBindingUtil;
|
||||||
|
import android.media.session.MediaSession;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
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.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -14,6 +21,8 @@ import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -60,10 +69,20 @@ public class MainActivity extends AppCompatActivity {
|
||||||
client.setToken(accountType, accountName, token);
|
client.setToken(accountType, accountName, token);
|
||||||
client.loadConfig(HttpUrl.parse(micropubBackend));
|
client.loadConfig(HttpUrl.parse(micropubBackend));
|
||||||
|
|
||||||
|
final View coordinator = findViewById(R.id.coordinator);
|
||||||
|
|
||||||
client.getResponse().observe(MainActivity.this, response -> {
|
client.getResponse().observe(MainActivity.this, response -> {
|
||||||
Log.i("micropub", "response received " + response.isSuccess());
|
Log.i("micropub", "response received " + response.isSuccess());
|
||||||
if (response.isSuccess()) {
|
if (response.isSuccess()) {
|
||||||
postModel.clear();
|
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());
|
Log.i("micropub", "media response received " + response.isSuccess());
|
||||||
if (response.isSuccess()) {
|
if (response.isSuccess()) {
|
||||||
postModel.setPhoto(response.getUrl());
|
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);
|
// setContentView(R.layout.activity_main);
|
||||||
ActivityMainBinding binding = DataBindingUtil.setContentView(this, 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) {
|
if (url != null) {
|
||||||
postModel.inReplyTo.set(urlOrNote);
|
postModel.inReplyTo.set(urlOrNote);
|
||||||
} else {
|
} else {
|
||||||
postModel.content.set(urlOrNote);
|
postModel.findReplyTo(urlOrNote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,9 +161,23 @@ public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
//noinspection SimplifiableIfStatement
|
//noinspection SimplifiableIfStatement
|
||||||
if (id == R.id.action_settings) {
|
if (id == R.id.action_settings) {
|
||||||
|
// TODO: implement some settings
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (id == R.id.action_send) {
|
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);
|
return super.onOptionsItemSelected(item);
|
||||||
|
@ -146,8 +197,15 @@ public class MainActivity extends AppCompatActivity {
|
||||||
Post post = postModel.getPost();
|
Post post = postModel.getPost();
|
||||||
client.createPost(post, token, HttpUrl.parse(micropubBackend));
|
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) {
|
public void galleryIntent(View view) {
|
||||||
|
@ -179,8 +237,10 @@ public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
client.postMedia(output, mimeType);
|
client.postMedia(output, mimeType);
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
|
Toast.makeText(this, "File not found: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||||
Log.e("micropub", "Error while copying image", e);
|
Log.e("micropub", "Error while copying image", e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
Toast.makeText(this, "Problem with IO " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||||
Log.e("micropub", "Error while copying image", e);
|
Log.e("micropub", "Error while copying image", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,18 +7,22 @@ import android.accounts.AuthenticatorException;
|
||||||
import android.accounts.OperationCanceledException;
|
import android.accounts.OperationCanceledException;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class OnTokenAcquired implements AccountManagerCallback<Bundle> {
|
public class OnTokenAcquired implements AccountManagerCallback<Bundle> {
|
||||||
private final TokenReady callback;
|
private final TokenReady callback;
|
||||||
|
private AuthError error;
|
||||||
private Activity activity;
|
private Activity activity;
|
||||||
|
|
||||||
public OnTokenAcquired(Activity activity, TokenReady callback) {
|
public OnTokenAcquired(Activity activity, TokenReady callback, AuthError error) {
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
|
this.error = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -39,10 +43,13 @@ public class OnTokenAcquired implements AccountManagerCallback<Bundle> {
|
||||||
callback.tokenReady(bundle.getString("accountType"), bundle.getString("authAccount"), token);
|
callback.tokenReady(bundle.getString("accountType"), bundle.getString("authAccount"), token);
|
||||||
} catch (OperationCanceledException e) {
|
} catch (OperationCanceledException e) {
|
||||||
Log.e("micropub", "on token acquired", e);
|
Log.e("micropub", "on token acquired", e);
|
||||||
|
error.handleErrorMessage(e.getMessage());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e("micropub", "on token acquired", e);
|
Log.e("micropub", "on token acquired", e);
|
||||||
|
error.handleErrorMessage(e.getMessage());
|
||||||
} catch (AuthenticatorException e) {
|
} catch (AuthenticatorException e) {
|
||||||
Log.e("micropub", "on token acquired", 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 android.databinding.ObservableList;
|
||||||
|
|
||||||
import java.util.Arrays;
|
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.Client;
|
||||||
import eu.stuifzand.micropub.client.Post;
|
import eu.stuifzand.micropub.client.Post;
|
||||||
|
@ -13,11 +15,18 @@ import eu.stuifzand.micropub.client.Syndication;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
public class PostViewModel extends ViewModel {
|
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> name = new ObservableField<>();
|
||||||
public final ObservableField<String> content = new ObservableField<>();
|
public final ObservableField<String> content = new ObservableField<>();
|
||||||
public final ObservableField<String> category = new ObservableField<>();
|
public final ObservableField<String> category = new ObservableField<>();
|
||||||
public final ObservableField<String> inReplyTo = new ObservableField<>();
|
public final ObservableField<String> inReplyTo = new ObservableField<>();
|
||||||
public final ObservableField<String> photo = new ObservableField<>();
|
public final ObservableField<String> photo = new ObservableField<>();
|
||||||
|
public final ObservableField<String> likeOf = new ObservableField<>();
|
||||||
|
|
||||||
public PostViewModel() {
|
public PostViewModel() {
|
||||||
this.name.set("");
|
this.name.set("");
|
||||||
|
@ -25,6 +34,7 @@ public class PostViewModel extends ViewModel {
|
||||||
this.category.set("");
|
this.category.set("");
|
||||||
this.inReplyTo.set("");
|
this.inReplyTo.set("");
|
||||||
this.photo.set("");
|
this.photo.set("");
|
||||||
|
this.likeOf.set("");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
|
@ -33,6 +43,26 @@ public class PostViewModel extends ViewModel {
|
||||||
this.category.set("");
|
this.category.set("");
|
||||||
this.inReplyTo.set("");
|
this.inReplyTo.set("");
|
||||||
this.photo.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) {
|
public void setPhoto(String url) {
|
||||||
|
@ -44,6 +74,7 @@ public class PostViewModel extends ViewModel {
|
||||||
if (!this.photo.get().equals("")) {
|
if (!this.photo.get().equals("")) {
|
||||||
post.setPhoto(this.photo.get());
|
post.setPhoto(this.photo.get());
|
||||||
}
|
}
|
||||||
|
post.setLikeOf(HttpUrl.parse(likeOf.get()));
|
||||||
return post;
|
return post;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import android.accounts.AccountAuthenticatorActivity;
|
||||||
import android.accounts.AccountAuthenticatorResponse;
|
import android.accounts.AccountAuthenticatorResponse;
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.RequiresApi;
|
import android.support.annotation.RequiresApi;
|
||||||
|
@ -15,6 +16,8 @@ import android.webkit.WebSettings;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
import android.webkit.WebViewClient;
|
import android.webkit.WebViewClient;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
import eu.stuifzand.micropub.R;
|
import eu.stuifzand.micropub.R;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
|
@ -37,7 +40,6 @@ public class AuthenticationActivity extends AccountAuthenticatorActivity {
|
||||||
final String me = intent.getStringExtra(WebsigninTask.ME);
|
final String me = intent.getStringExtra(WebsigninTask.ME);
|
||||||
final AccountAuthenticatorResponse response = intent.getParcelableExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE);
|
final AccountAuthenticatorResponse response = intent.getParcelableExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE);
|
||||||
|
|
||||||
|
|
||||||
WebView webview = findViewById(R.id.webview);
|
WebView webview = findViewById(R.id.webview);
|
||||||
WebSettings webSettings = webview.getSettings();
|
WebSettings webSettings = webview.getSettings();
|
||||||
webSettings.setJavaScriptEnabled(true);
|
webSettings.setJavaScriptEnabled(true);
|
||||||
|
@ -46,7 +48,7 @@ public class AuthenticationActivity extends AccountAuthenticatorActivity {
|
||||||
HttpUrl.Builder builder = HttpUrl.parse(endpoint).newBuilder();
|
HttpUrl.Builder builder = HttpUrl.parse(endpoint).newBuilder();
|
||||||
builder.setQueryParameter("me", me)
|
builder.setQueryParameter("me", me)
|
||||||
.setQueryParameter("client_id", "https://stuifzand.eu/micropub")
|
.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("response_type", "code")
|
||||||
.setQueryParameter("state", "1234") // @TODO use random states, check the state later
|
.setQueryParameter("state", "1234") // @TODO use random states, check the state later
|
||||||
.setQueryParameter("scope", "create edit update post delete"); // @TODO use different scope
|
.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)
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
@Override
|
@Override
|
||||||
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
|
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());
|
Log.i("micropub", error.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,10 +66,10 @@ public class AuthenticationActivity extends AccountAuthenticatorActivity {
|
||||||
public boolean shouldOverrideUrlLoading(WebView viewx, WebResourceRequest request) {
|
public boolean shouldOverrideUrlLoading(WebView viewx, WebResourceRequest request) {
|
||||||
Log.i("micropub", "New API: " + request.getUrl().toString());
|
Log.i("micropub", "New API: " + request.getUrl().toString());
|
||||||
String url = request.getUrl().toString();
|
String url = request.getUrl().toString();
|
||||||
if (url.startsWith("https://stuifzand.eu/micropub-auth")) {
|
if (url.startsWith("wrimini://oauth")) {
|
||||||
HttpUrl httpUrl = HttpUrl.parse(url);
|
Uri uri = Uri.parse(url);
|
||||||
String code = httpUrl.queryParameter("code");
|
String code = uri.getQueryParameter("code");
|
||||||
String state = httpUrl.queryParameter("state");
|
//String state = httpUrl.queryParameter("state");
|
||||||
|
|
||||||
new VerifyAuthenticationTask(response, AuthenticationActivity.this).execute(endpoint, me, code);
|
new VerifyAuthenticationTask(response, AuthenticationActivity.this).execute(endpoint, me, code);
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class Authenticator extends AbstractAccountAuthenticator {
|
||||||
if (TextUtils.isEmpty(authToken)) {
|
if (TextUtils.isEmpty(authToken)) {
|
||||||
RequestBody formBody = new FormBody.Builder()
|
RequestBody formBody = new FormBody.Builder()
|
||||||
.add("code", am.getPassword(account))
|
.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("client_id", "https://stuifzand.eu/micropub")
|
||||||
.add("me", account.name)
|
.add("me", account.name)
|
||||||
.add("grant_type", "authorization_code")
|
.add("grant_type", "authorization_code")
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package eu.stuifzand.micropub.auth;
|
package eu.stuifzand.micropub.auth;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
import android.accounts.AccountAuthenticatorResponse;
|
import android.accounts.AccountAuthenticatorResponse;
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -70,7 +71,7 @@ public class VerifyAuthenticationTask extends AsyncTask<String, Void, VerifyAuth
|
||||||
|
|
||||||
RequestBody formBody = new FormBody.Builder()
|
RequestBody formBody = new FormBody.Builder()
|
||||||
.add("code", code)
|
.add("code", code)
|
||||||
.add("redirect_uri", "https://stuifzand.eu/micropub-auth")
|
.add("redirect_uri", "wrimini://oauth")
|
||||||
.add("client_id", "https://stuifzand.eu/micropub")
|
.add("client_id", "https://stuifzand.eu/micropub")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -141,7 +142,7 @@ public class VerifyAuthenticationTask extends AsyncTask<String, Void, VerifyAuth
|
||||||
this.activity.finishLogin(intent);
|
this.activity.finishLogin(intent);
|
||||||
this.response.onResult(bundle);
|
this.response.onResult(bundle);
|
||||||
} else {
|
} 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.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.jsoup.Connection;
|
import org.jsoup.Connection;
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
|
@ -49,6 +50,7 @@ public class WebsigninTask extends AsyncTask<String, Void, Bundle> {
|
||||||
String profileUrl = strings[0];
|
String profileUrl = strings[0];
|
||||||
bundle.putString(ME, profileUrl);
|
bundle.putString(ME, profileUrl);
|
||||||
Connection conn = Jsoup.connect(profileUrl);
|
Connection conn = Jsoup.connect(profileUrl);
|
||||||
|
conn.timeout(10*1000);
|
||||||
Document doc = conn.get();
|
Document doc = conn.get();
|
||||||
Connection.Response resp = conn.response();
|
Connection.Response resp = conn.response();
|
||||||
|
|
||||||
|
@ -81,7 +83,8 @@ public class WebsigninTask extends AsyncTask<String, Void, Bundle> {
|
||||||
linkHeaders.put(rel, link.attr("href"));
|
linkHeaders.put(rel, link.attr("href"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (Exception e) {
|
||||||
|
bundle.putString("ERROR", e.getMessage());
|
||||||
return bundle;
|
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());
|
Log.i("micropub", bundle.toString());
|
||||||
return bundle;
|
return bundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Bundle bundle) {
|
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 intent = new Intent(this.activity, AuthenticationActivity.class);
|
||||||
intent.putExtras(activity.getIntent());
|
intent.putExtras(activity.getIntent());
|
||||||
intent.putExtras(bundle);
|
intent.putExtras(bundle);
|
||||||
|
|
|
@ -9,23 +9,27 @@ public class Post {
|
||||||
private String[] categories;
|
private String[] categories;
|
||||||
private String[] syndicationUids;
|
private String[] syndicationUids;
|
||||||
private String photo;
|
private String photo;
|
||||||
|
private HttpUrl likeOf;
|
||||||
|
|
||||||
public Post(String content) {
|
public Post(String content) {
|
||||||
this.content = content;
|
if (content.equals("")) {
|
||||||
|
this.content=null;
|
||||||
|
} else {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
this.categories = new String[]{};
|
this.categories = new String[]{};
|
||||||
this.syndicationUids = new String[]{};
|
this.syndicationUids = new String[]{};
|
||||||
}
|
}
|
||||||
|
|
||||||
public Post(String name, String content) {
|
public Post(String name, String content) {
|
||||||
this.name = name;
|
this(content);
|
||||||
this.content = content;
|
|
||||||
this.categories = new String[]{};
|
this.categories = new String[]{};
|
||||||
|
this.name = name;
|
||||||
this.syndicationUids = new String[]{};
|
this.syndicationUids = new String[]{};
|
||||||
}
|
}
|
||||||
|
|
||||||
public Post(String name, String content, String categories) {
|
public Post(String name, String content, String categories) {
|
||||||
this.name = name;
|
this(name, content);
|
||||||
this.content = content;
|
|
||||||
this.categories = categories.split("\\s+");
|
this.categories = categories.split("\\s+");
|
||||||
if (this.categories.length == 1 && this.categories[0].length() == 0) {
|
if (this.categories.length == 1 && this.categories[0].length() == 0) {
|
||||||
this.categories = new String[]{};
|
this.categories = new String[]{};
|
||||||
|
@ -82,4 +86,20 @@ public class Post {
|
||||||
public boolean hasPhoto() {
|
public boolean hasPhoto() {
|
||||||
return this.photo != null;
|
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
|
@Override
|
||||||
protected Void doInBackground(String... strings) {
|
protected Void doInBackground(String... strings) {
|
||||||
FormBody.Builder builder = new FormBody.Builder();
|
FormBody.Builder builder = new FormBody.Builder();
|
||||||
builder.add("h", "entry")
|
builder.add("h", "entry");
|
||||||
.add("content", post.getContent());
|
|
||||||
|
|
||||||
|
if (post.hasContent()) {
|
||||||
|
builder.add("content", post.getContent());
|
||||||
|
}
|
||||||
for (String cat : post.getCategories()) {
|
for (String cat : post.getCategories()) {
|
||||||
builder.add("category[]", cat);
|
builder.add("category[]", cat);
|
||||||
}
|
}
|
||||||
|
@ -54,6 +56,10 @@ class PostTask extends AsyncTask<String, Void, Void> {
|
||||||
builder.add("photo", post.getPhoto());
|
builder.add("photo", post.getPhoto());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (post.hasLikeOf()) {
|
||||||
|
builder.add("like-of", post.getLikeOf());
|
||||||
|
}
|
||||||
|
|
||||||
RequestBody formBody = builder.build();
|
RequestBody formBody = builder.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
|
@ -76,15 +82,16 @@ class PostTask extends AsyncTask<String, Void, Void> {
|
||||||
okhttp3.Response httpResponse = null;
|
okhttp3.Response httpResponse = null;
|
||||||
try {
|
try {
|
||||||
httpResponse = call.execute();
|
httpResponse = call.execute();
|
||||||
if (httpResponse.code() == 201) {
|
int code = httpResponse.code();
|
||||||
|
if (code == 201) {
|
||||||
String location = httpResponse.header("Location");
|
String location = httpResponse.header("Location");
|
||||||
response.postValue(Response.successful(location));
|
response.postValue(Response.successful(location));
|
||||||
} else {
|
} else {
|
||||||
response.postValue(Response.failed());
|
response.postValue(Response.failed(httpResponse.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
response.postValue(Response.failed());
|
response.postValue(Response.failed(e.getMessage()));
|
||||||
} finally {
|
} finally {
|
||||||
if (httpResponse != null) {
|
if (httpResponse != null) {
|
||||||
httpResponse.close();
|
httpResponse.close();
|
||||||
|
|
|
@ -13,8 +13,8 @@ public class Response {
|
||||||
this.url = url;
|
this.url = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Response failed() {
|
public static Response failed(String why) {
|
||||||
return new Response(false);
|
return new Response(false, why);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Response successful(String url) {
|
public static Response successful(String url) {
|
||||||
|
@ -24,8 +24,8 @@ public class Response {
|
||||||
public boolean isSuccess() {
|
public boolean isSuccess() {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
return url;
|
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>
|
</data>
|
||||||
|
|
||||||
<android.support.design.widget.CoordinatorLayout
|
<android.support.design.widget.CoordinatorLayout
|
||||||
|
android:id="@+id/coordinator"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context="eu.stuifzand.micropub.MainActivity">
|
tools:context="eu.stuifzand.micropub.MainActivity">
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="viewModel"
|
name="viewModel"
|
||||||
type="eu.stuifzand.micropub.PostViewModel" />
|
type="eu.stuifzand.micropub.PostViewModel" />
|
||||||
|
@ -14,19 +13,23 @@
|
||||||
type="eu.stuifzand.micropub.client.Client" />
|
type="eu.stuifzand.micropub.client.Client" />
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:id="@+id/scrollView"
|
android:id="@+id/scrollView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/colorPrimary"
|
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:context="eu.stuifzand.micropub.MainActivity"
|
||||||
tools:showIn="@layout/activity_main">
|
tools:showIn="@layout/activity_main">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<android.support.constraint.ConstraintLayout
|
<android.support.constraint.ConstraintLayout
|
||||||
|
@ -34,8 +37,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:overScrollMode="always"
|
android:overScrollMode="always"
|
||||||
android:paddingTop="8dp"
|
android:paddingTop="8dp"
|
||||||
android:scrollbars="vertical"
|
android:scrollbars="vertical">
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
|
||||||
|
|
||||||
<android.support.design.widget.TextInputLayout
|
<android.support.design.widget.TextInputLayout
|
||||||
android:id="@+id/editInReplyToLayout"
|
android:id="@+id/editInReplyToLayout"
|
||||||
|
@ -62,6 +64,32 @@
|
||||||
|
|
||||||
</android.support.design.widget.TextInputLayout>
|
</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.support.design.widget.TextInputLayout
|
||||||
android:id="@+id/contentLayout"
|
android:id="@+id/contentLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -71,7 +99,7 @@
|
||||||
app:counterEnabled="true"
|
app:counterEnabled="true"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/editInReplyToLayout">
|
app:layout_constraintTop_toBottomOf="@+id/editNameLayout">
|
||||||
|
|
||||||
<android.support.design.widget.TextInputEditText
|
<android.support.design.widget.TextInputEditText
|
||||||
android:id="@+id/content"
|
android:id="@+id/content"
|
||||||
|
@ -134,33 +162,12 @@
|
||||||
<ListView
|
<ListView
|
||||||
android:id="@+id/listSyndication"
|
android:id="@+id/listSyndication"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="115dp"
|
android:layout_height="69dp"
|
||||||
|
android:isScrollContainer="false"
|
||||||
app:list="@{client.syndicates}" />
|
app:list="@{client.syndicates}" />
|
||||||
|
|
||||||
</LinearLayout>
|
</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.support.design.widget.TextInputLayout
|
||||||
android:id="@+id/editPhotoLayout"
|
android:id="@+id/editPhotoLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -174,7 +181,7 @@
|
||||||
<android.support.design.widget.TextInputEditText
|
<android.support.design.widget.TextInputEditText
|
||||||
android:id="@+id/editPhoto"
|
android:id="@+id/editPhoto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="56sp"
|
android:layout_height="52dp"
|
||||||
android:ems="10"
|
android:ems="10"
|
||||||
android:imeOptions="actionDone"
|
android:imeOptions="actionDone"
|
||||||
android:inputType="text"
|
android:inputType="text"
|
||||||
|
@ -186,6 +193,5 @@
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</layout>
|
</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"
|
android:title="@string/action_settings"
|
||||||
app:showAsAction="never" />
|
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:orderInCategory="10"
|
||||||
android:title="Send"
|
android:title="@string/action_photo"
|
||||||
android:icon="@drawable/ic_menu_send"
|
app:showAsAction="ifRoom" />
|
||||||
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>
|
</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="post">Post</string>
|
||||||
<string name="syndication">Syndicate to</string>
|
<string name="syndication">Syndicate to</string>
|
||||||
<string name="user_agent">Wrimini</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>
|
</resources>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user