Following Misskey - step 1
This commit is contained in:
parent
2ed70688b9
commit
4c00ba823b
|
@ -409,8 +409,9 @@ public abstract class BaseMainActivity extends BaseActivity
|
|||
SubMenu submMastodon = popup.getMenu().findItem(R.id.action_show_mastodon).getSubMenu();
|
||||
SubMenu submPeertube = popup.getMenu().findItem(R.id.action_show_peertube).getSubMenu();
|
||||
SubMenu submPixelfed = popup.getMenu().findItem(R.id.action_show_pixelfed).getSubMenu();
|
||||
SubMenu submMisskey = popup.getMenu().findItem(R.id.action_show_misskey).getSubMenu();
|
||||
SubMenu submChannel = popup.getMenu().findItem(R.id.action_show_channel).getSubMenu();
|
||||
int i = 0, j = 0 , k = 0;
|
||||
int i = 0, j = 0 , k = 0, l = 0 , m = 0;
|
||||
for (RemoteInstance remoteInstance : remoteInstances) {
|
||||
if (remoteInstance.getType() == null || remoteInstance.getType().equals("MASTODON")) {
|
||||
MenuItem itemPlaceHolder = submMastodon.findItem(R.id.mastodon_instances);
|
||||
|
@ -506,11 +507,42 @@ public abstract class BaseMainActivity extends BaseActivity
|
|||
});
|
||||
j++;
|
||||
}
|
||||
if (remoteInstance.getType() == null || remoteInstance.getType().equals("MISSKEY")) {
|
||||
MenuItem itemPlaceHolder = submPixelfed.findItem(R.id.misskey_instance);
|
||||
if( itemPlaceHolder != null)
|
||||
itemPlaceHolder.setVisible(false);
|
||||
MenuItem item = submMisskey.add(0, l, Menu.NONE, remoteInstance.getHost());
|
||||
item.setIcon(R.drawable.misskey);
|
||||
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
DisplayStatusFragment statusFragment;
|
||||
Bundle bundle = new Bundle();
|
||||
statusFragment = new DisplayStatusFragment();
|
||||
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE);
|
||||
bundle.putString("remote_instance", remoteInstance.getHost());
|
||||
statusFragment.setArguments(bundle);
|
||||
String fragmentTag = "REMOTE_INSTANCE";
|
||||
instance_id = remoteInstance.getDbID();
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
fragmentManager.beginTransaction()
|
||||
.replace(R.id.main_app_container, statusFragment, fragmentTag).commit();
|
||||
main_app_container.setVisibility(View.VISIBLE);
|
||||
viewPager.setVisibility(View.GONE);
|
||||
tabLayout.setVisibility(View.GONE);
|
||||
toolbarTitle.setVisibility(View.VISIBLE);
|
||||
delete_instance.setVisibility(View.VISIBLE);
|
||||
toolbarTitle.setText(remoteInstance.getHost());
|
||||
return false;
|
||||
}
|
||||
});
|
||||
l++;
|
||||
}
|
||||
if (remoteInstance.getType() == null || remoteInstance.getType().equals("PEERTUBE")) {
|
||||
MenuItem itemPlaceHolder = submPeertube.findItem(R.id.peertube_instances);
|
||||
if( itemPlaceHolder != null)
|
||||
itemPlaceHolder.setVisible(false);
|
||||
MenuItem item = submPeertube.add(0, j, Menu.NONE, remoteInstance.getHost());
|
||||
MenuItem item = submPeertube.add(0, m, Menu.NONE, remoteInstance.getHost());
|
||||
item.setIcon(R.drawable.peertube_icon);
|
||||
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||
@Override
|
||||
|
@ -535,7 +567,7 @@ public abstract class BaseMainActivity extends BaseActivity
|
|||
return false;
|
||||
}
|
||||
});
|
||||
j++;
|
||||
m++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -568,6 +600,8 @@ public abstract class BaseMainActivity extends BaseActivity
|
|||
new HttpsConnection(BaseMainActivity.this).get("https://" + instanceName + "/api/v1/videos/", 10, null, null);
|
||||
else if( radioGroup.getCheckedRadioButtonId() == R.id.pixelfed_instance) {
|
||||
new HttpsConnection(BaseMainActivity.this).get("https://" + instanceName + "/api/v1/timelines/public", 10, null, null);
|
||||
}else if( radioGroup.getCheckedRadioButtonId() == R.id.misskey_instance) {
|
||||
new HttpsConnection(BaseMainActivity.this).post("https://" + instanceName + "/api/notes/local-timeline", 10, null, null);
|
||||
}
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
|
@ -579,6 +613,8 @@ public abstract class BaseMainActivity extends BaseActivity
|
|||
new InstancesDAO(BaseMainActivity.this, db).insertInstance(instanceName, "PEERTUBE");
|
||||
else if( radioGroup.getCheckedRadioButtonId() == R.id.pixelfed_instance)
|
||||
new InstancesDAO(BaseMainActivity.this, db).insertInstance(instanceName, "PIXELFED");
|
||||
else if( radioGroup.getCheckedRadioButtonId() == R.id.misskey_instance)
|
||||
new InstancesDAO(BaseMainActivity.this, db).insertInstance(instanceName, "MISSKEY");
|
||||
DisplayStatusFragment statusFragment;
|
||||
Bundle bundle = new Bundle();
|
||||
statusFragment = new DisplayStatusFragment();
|
||||
|
|
|
@ -176,7 +176,15 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
|
|||
status.setType(action);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
}else if(remoteInstanceObj != null && remoteInstanceObj.size() > 0 && remoteInstanceObj.get(0).getType().equals("MISSKEY")){
|
||||
apiResponse = api.getMisskey(this.instanceName, max_id);
|
||||
List<fr.gouv.etalab.mastodon.client.Entities.Status> statusesTemp = apiResponse.getStatuses();
|
||||
if( statusesTemp != null){
|
||||
for(fr.gouv.etalab.mastodon.client.Entities.Status status: statusesTemp){
|
||||
status.setType(action);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
apiResponse = api.getPeertube(this.instanceName, max_id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ package fr.gouv.etalab.mastodon.client;
|
|||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
@ -1039,6 +1040,39 @@ public class API {
|
|||
apiResponse.setHowToVideos(howToVideos);
|
||||
return apiResponse;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves Peertube videos from an instance *synchronously*
|
||||
* @return APIResponse
|
||||
*/
|
||||
public APIResponse getMisskey(String instance, String max_id) {
|
||||
|
||||
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
if( max_id != null)
|
||||
params.put("untilId",max_id);
|
||||
try {
|
||||
statuses = new ArrayList<>();
|
||||
HttpsConnection httpsConnection = new HttpsConnection(context);
|
||||
String response = httpsConnection.post(String.format("https://"+instance+"/api/notes/local-timeline", max_id), 60, params, null);
|
||||
apiResponse.setSince_id(httpsConnection.getSince_id());
|
||||
apiResponse.setMax_id(httpsConnection.getMax_id());
|
||||
statuses = parseNotes(context, instance, new JSONArray(response));
|
||||
} catch (HttpsConnection.HttpsConnectionException e) {
|
||||
setError(e.getStatusCode(), e);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (KeyManagementException e) {
|
||||
e.printStackTrace();
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
apiResponse.setStatuses(statuses);
|
||||
return apiResponse;
|
||||
}
|
||||
/**
|
||||
* Retrieves public timeline for the account *synchronously*
|
||||
* @param local boolean only local timeline
|
||||
|
@ -3134,6 +3168,150 @@ public class API {
|
|||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse json response for several notes (Misskey)
|
||||
* @param jsonArray JSONArray
|
||||
* @return List<Status>
|
||||
*/
|
||||
public static List<Status> parseNotes(Context context, String instance, JSONArray jsonArray){
|
||||
|
||||
List<Status> statuses = new ArrayList<>();
|
||||
try {
|
||||
int i = 0;
|
||||
while (i < jsonArray.length() ){
|
||||
|
||||
JSONObject resobj = jsonArray.getJSONObject(i);
|
||||
Status status = parseNotes(context, instance, resobj);
|
||||
i++;
|
||||
statuses.add(status);
|
||||
}
|
||||
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return statuses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse json response for unique note (misskey)
|
||||
* @param resobj JSONObject
|
||||
* @return Status
|
||||
*/
|
||||
@SuppressWarnings("InfiniteRecursion")
|
||||
public static Status parseNotes(Context context, String instance, JSONObject resobj){
|
||||
Status status = new Status();
|
||||
try {
|
||||
status.setId(resobj.get("id").toString());
|
||||
status.setUri("https://" + instance + "/notes/" + resobj.get("id").toString());
|
||||
status.setCreated_at(Helper.mstStringToDate(context, resobj.get("createdAt").toString()));
|
||||
status.setIn_reply_to_id(resobj.get("replyId").toString());
|
||||
status.setSensitive(false);
|
||||
if(resobj.get("cw") != null && !resobj.get("cw").toString().equals("null"))
|
||||
status.setSpoiler_text(resobj.get("cw").toString());
|
||||
try {
|
||||
status.setVisibility(resobj.get("visibility").toString());
|
||||
}catch (Exception e){status.setVisibility("public"); e.printStackTrace();}
|
||||
status.setUrl("https://" + instance + "/notes/" + resobj.get("id").toString());
|
||||
//Retrieves attachments
|
||||
JSONArray arrayAttachement = resobj.getJSONArray("media");
|
||||
ArrayList<Attachment> attachments = new ArrayList<>();
|
||||
if( arrayAttachement != null){
|
||||
for(int j = 0 ; j < arrayAttachement.length() ; j++){
|
||||
JSONObject attObj = arrayAttachement.getJSONObject(j);
|
||||
Attachment attachment = new Attachment();
|
||||
attachment.setId(attObj.get("id").toString());
|
||||
attachment.setPreview_url(attObj.get("thumbnailUrl").toString());
|
||||
attachment.setRemote_url(attObj.get("url").toString());
|
||||
if( attObj.get("type").toString().contains("/")){
|
||||
attachment.setType(attObj.get("type").toString().split("/")[0]);
|
||||
}else
|
||||
attachment.setType(attObj.get("type").toString());
|
||||
attachment.setText_url(attObj.get("url").toString());
|
||||
attachment.setUrl(attObj.get("url").toString());
|
||||
if(attObj.get("isSensitive").toString().equals("true")){
|
||||
status.setSensitive(true);
|
||||
}
|
||||
try {
|
||||
attachment.setDescription(attObj.get("comment").toString());
|
||||
}catch (JSONException ignore){ignore.printStackTrace();}
|
||||
attachments.add(attachment);
|
||||
}
|
||||
}
|
||||
try {
|
||||
status.setCard(parseCardResponse(resobj.getJSONObject("card")));
|
||||
}catch (Exception e){status.setCard(null);}
|
||||
|
||||
status.setMedia_attachments(attachments);
|
||||
//Retrieves mentions
|
||||
List<Mention> mentions = new ArrayList<>();
|
||||
|
||||
status.setAccount(parseMisskeyAccountResponse(context, instance, resobj.getJSONObject("user")));
|
||||
status.setContent(resobj.get("text").toString());
|
||||
try{
|
||||
status.setReplies_count(Integer.valueOf(resobj.get("repliesCount").toString()));
|
||||
}catch (Exception e){
|
||||
status.setReplies_count(-1);
|
||||
}
|
||||
try {
|
||||
status.setFavourited(Boolean.valueOf(resobj.get("isFavorited").toString()));
|
||||
}catch (Exception e){
|
||||
status.setFavourited(false);
|
||||
}
|
||||
try{
|
||||
if(resobj.getJSONObject("renoteId") != null && !resobj.getJSONObject("renoteId").toString().equals("null"))
|
||||
status.setReblog(parseStatuses(context, resobj.getJSONObject("renote")));
|
||||
}catch (Exception ignored){}
|
||||
|
||||
status.setMentions(mentions);
|
||||
//Retrieves tags
|
||||
List<Tag> tags = new ArrayList<>();
|
||||
JSONArray arrayTag = resobj.getJSONArray("tags");
|
||||
if( arrayTag != null){
|
||||
for(int j = 0 ; j < arrayTag.length() ; j++){
|
||||
JSONObject tagObj = arrayTag.getJSONObject(j);
|
||||
Tag tag = new Tag();
|
||||
tag.setName(tagObj.get("name").toString());
|
||||
tag.setUrl(tagObj.get("url").toString());
|
||||
tags.add(tag);
|
||||
}
|
||||
}
|
||||
status.setTags(tags);
|
||||
|
||||
//Retrieves emjis
|
||||
List<Emojis> emojiList = new ArrayList<>();
|
||||
try {
|
||||
JSONArray emojisTag = resobj.getJSONArray("emojis");
|
||||
if( emojisTag != null){
|
||||
for(int j = 0 ; j < emojisTag.length() ; j++){
|
||||
JSONObject emojisObj = emojisTag.getJSONObject(j);
|
||||
Emojis emojis = parseEmojis(emojisObj);
|
||||
emojiList.add(emojis);
|
||||
}
|
||||
}
|
||||
status.setEmojis(emojiList);
|
||||
}catch (Exception e){
|
||||
status.setEmojis(new ArrayList<>());
|
||||
}
|
||||
|
||||
//Retrieve Application
|
||||
Application application = new Application();
|
||||
try {
|
||||
if(resobj.getJSONObject("application") != null){
|
||||
application.setName(resobj.getJSONObject("application").getString("name"));
|
||||
application.setWebsite(resobj.getJSONObject("application").getString("website"));
|
||||
}
|
||||
}catch (Exception e){
|
||||
application = new Application();
|
||||
}
|
||||
status.setApplication(application);
|
||||
|
||||
|
||||
} catch (JSONException ignored) {} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
/**
|
||||
* Parse json response an unique instance
|
||||
* @param resobj JSONObject
|
||||
|
@ -3421,6 +3599,56 @@ public class API {
|
|||
return account;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse json response an unique account
|
||||
* @param resobj JSONObject
|
||||
* @return Account
|
||||
*/
|
||||
@SuppressWarnings("InfiniteRecursion")
|
||||
private static Account parseMisskeyAccountResponse(Context context, String instance, JSONObject resobj){
|
||||
|
||||
Log.v(Helper.TAG,"resobj= " + resobj);
|
||||
Account account = new Account();
|
||||
try {
|
||||
account.setId(resobj.get("id").toString());
|
||||
account.setUsername(resobj.get("username").toString());
|
||||
String host = resobj.get("host").toString();
|
||||
String acct;
|
||||
if( host == null || host.equals("null"))
|
||||
acct = resobj.get("username").toString();
|
||||
else
|
||||
acct = resobj.get("username").toString() + "@" + host;
|
||||
account.setAcct(acct);
|
||||
account.setDisplay_name(resobj.get("name").toString());
|
||||
account.setCreated_at(new Date());
|
||||
|
||||
account.setUrl("https://" + instance + "/@"+account.getUsername());
|
||||
account.setAvatar(resobj.get("avatarUrl").toString());
|
||||
account.setAvatar_static(resobj.get("avatarUrl").toString());
|
||||
try {
|
||||
account.setBot(Boolean.parseBoolean(resobj.get("isBot").toString()));
|
||||
}catch (Exception e){
|
||||
account.setBot(false);
|
||||
}
|
||||
//Retrieves emjis
|
||||
List<Emojis> emojiList = new ArrayList<>();
|
||||
try {
|
||||
JSONArray emojisTag = resobj.getJSONArray("emojis");
|
||||
if( emojisTag != null){
|
||||
for(int j = 0 ; j < emojisTag.length() ; j++){
|
||||
JSONObject emojisObj = emojisTag.getJSONObject(j);
|
||||
Emojis emojis = parseEmojis(emojisObj);
|
||||
emojiList.add(emojis);
|
||||
}
|
||||
}
|
||||
account.setEmojis(emojiList);
|
||||
}catch (Exception e){
|
||||
account.setEmojis(new ArrayList<>());
|
||||
}
|
||||
} catch (JSONException ignored) {}
|
||||
return account;
|
||||
}
|
||||
/**
|
||||
* Parse json response for list of accounts
|
||||
* @param jsonArray JSONArray
|
||||
|
|
|
@ -437,7 +437,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
boolean isCompactMode = sharedpreferences.getBoolean(Helper.SET_COMPACT_MODE, false);
|
||||
if( type == RetrieveFeedsAsyncTask.Type.CONTEXT && position == conversationPosition)
|
||||
return FOCUSED_STATUS;
|
||||
else if( !Helper.filterToots(context, statuses.get(position), timedMute, type))
|
||||
else if( type != RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE && !Helper.filterToots(context, statuses.get(position), timedMute, type))
|
||||
return HIDDEN_STATUS;
|
||||
else
|
||||
return isCompactMode?COMPACT_STATUS:DISPLAYED_STATUS;
|
||||
|
@ -1091,8 +1091,8 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
|
||||
}
|
||||
|
||||
|
||||
holder.status_mention_spoiler.setText(Helper.makeMentionsClick(context,status.getMentions()), TextView.BufferType.SPANNABLE);
|
||||
if( status.getMentions() != null)
|
||||
holder.status_mention_spoiler.setText(Helper.makeMentionsClick(context,status.getMentions()), TextView.BufferType.SPANNABLE);
|
||||
holder.status_mention_spoiler.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
||||
if( getItemViewType(viewHolder.getAdapterPosition()) != COMPACT_STATUS ) {
|
||||
|
|
|
@ -179,7 +179,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
|||
statusListAdapter = new StatusListAdapter(context, tagTimeline, targetedId, isOnWifi, this.statuses);
|
||||
lv_status.setAdapter(statusListAdapter);
|
||||
}
|
||||
}else if( search_peertube == null && (instanceType == null || instanceType.equals("MASTODON") || instanceType.equals("PIXELFED"))) {
|
||||
}else if( search_peertube == null && (instanceType == null || instanceType.equals("MASTODON") || instanceType.equals("PIXELFED") || instanceType.equals("MISSKEY"))) {
|
||||
BaseMainActivity.displayPeertube = null;
|
||||
if( instanceType != null && instanceType.equals("PIXELFED"))
|
||||
type = RetrieveFeedsAsyncTask.Type.PIXELFED;
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 500 B |
Binary file not shown.
After Width: | Height: | Size: 650 B |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
|
@ -31,5 +31,10 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:text="@string/pixelfed_instance"
|
||||
/>
|
||||
<RadioButton android:id="@+id/misskey_instance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/misskey_instance"
|
||||
/>
|
||||
</RadioGroup>
|
||||
</LinearLayout>
|
|
@ -37,6 +37,16 @@
|
|||
<item android:id="@+id/pixelfed_instance" android:title="@string/no_pixelfed_instance"/>
|
||||
</menu>
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/action_show_misskey"
|
||||
android:title="Misskey"
|
||||
android:icon="@drawable/misskey"
|
||||
app:showAsAction="never"
|
||||
>
|
||||
<menu>
|
||||
<item android:id="@+id/misskey_instance" android:title="@string/no_misskey_instance"/>
|
||||
</menu>
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/action_show_channel"
|
||||
android:title="@string/channel"
|
||||
|
|
|
@ -784,6 +784,8 @@
|
|||
<string name="some_words_all">All these words (space-separated)</string>
|
||||
<string name="some_words_none">None of these words (space-separated)</string>
|
||||
<string name="change_tag_column">Change column name</string>
|
||||
<string name="no_misskey_instance">No Misskey instances</string>
|
||||
<string name="misskey_instance">Misskey instance</string>
|
||||
<!-- end languages -->
|
||||
|
||||
</resources>
|
Loading…
Reference in New Issue