420 lines
22 KiB
Java
420 lines
22 KiB
Java
package app.fedilab.android.mastodon.activities;
|
|
/* Copyright 2022 Thomas Schneider
|
|
*
|
|
* This file is a part of Fedilab
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
* Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
|
* see <http://www.gnu.org/licenses>. */
|
|
|
|
|
|
import android.content.Intent;
|
|
import android.content.SharedPreferences;
|
|
import android.os.Bundle;
|
|
import android.text.Editable;
|
|
import android.text.TextWatcher;
|
|
import android.view.Menu;
|
|
import android.view.MenuItem;
|
|
import android.view.View;
|
|
import android.view.WindowManager;
|
|
import android.view.inputmethod.InputMethodManager;
|
|
import android.widget.ArrayAdapter;
|
|
import android.widget.Toast;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.appcompat.app.AlertDialog;
|
|
import androidx.lifecycle.ViewModelProvider;
|
|
import androidx.preference.PreferenceManager;
|
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
|
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
import app.fedilab.android.BuildConfig;
|
|
import app.fedilab.android.R;
|
|
import app.fedilab.android.activities.MainActivity;
|
|
import app.fedilab.android.databinding.ActivityReorderTabsBinding;
|
|
import app.fedilab.android.databinding.PopupSearchInstanceBinding;
|
|
import app.fedilab.android.mastodon.client.entities.app.BottomMenu;
|
|
import app.fedilab.android.mastodon.client.entities.app.CachedBundle;
|
|
import app.fedilab.android.mastodon.client.entities.app.InstanceSocial;
|
|
import app.fedilab.android.mastodon.client.entities.app.Pinned;
|
|
import app.fedilab.android.mastodon.client.entities.app.PinnedTimeline;
|
|
import app.fedilab.android.mastodon.client.entities.app.RemoteInstance;
|
|
import app.fedilab.android.mastodon.client.entities.app.Timeline;
|
|
import app.fedilab.android.mastodon.exception.DBException;
|
|
import app.fedilab.android.mastodon.helper.Helper;
|
|
import app.fedilab.android.mastodon.helper.PinnedTimelineHelper;
|
|
import app.fedilab.android.mastodon.helper.itemtouchhelper.OnStartDragListener;
|
|
import app.fedilab.android.mastodon.helper.itemtouchhelper.SimpleItemTouchHelperCallback;
|
|
import app.fedilab.android.mastodon.ui.drawer.ReorderBottomMenuAdapter;
|
|
import app.fedilab.android.mastodon.ui.drawer.ReorderTabAdapter;
|
|
import app.fedilab.android.mastodon.viewmodel.mastodon.InstanceSocialVM;
|
|
import app.fedilab.android.mastodon.viewmodel.mastodon.ReorderVM;
|
|
import es.dmoral.toasty.Toasty;
|
|
import okhttp3.Call;
|
|
import okhttp3.Callback;
|
|
import okhttp3.FormBody;
|
|
import okhttp3.OkHttpClient;
|
|
import okhttp3.Request;
|
|
import okhttp3.RequestBody;
|
|
import okhttp3.Response;
|
|
|
|
|
|
public class ReorderTimelinesActivity extends BaseBarActivity implements OnStartDragListener {
|
|
|
|
|
|
private ItemTouchHelper touchHelper;
|
|
private ReorderTabAdapter reorderTabAdapter;
|
|
private ReorderBottomMenuAdapter reorderBottomMenuAdapter;
|
|
private boolean searchInstanceRunning;
|
|
private String oldSearch;
|
|
private Pinned pinned;
|
|
private BottomMenu bottomMenu;
|
|
private ActivityReorderTabsBinding binding;
|
|
private boolean changes;
|
|
private boolean bottomChanges;
|
|
private boolean update;
|
|
|
|
public void setChanges(boolean changes) {
|
|
this.changes = changes;
|
|
}
|
|
|
|
public void setBottomChanges(boolean bottomChanges) {
|
|
this.bottomChanges = bottomChanges;
|
|
}
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
|
|
binding = ActivityReorderTabsBinding.inflate(getLayoutInflater());
|
|
setContentView(binding.getRoot());
|
|
searchInstanceRunning = false;
|
|
if (getSupportActionBar() != null) {
|
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
|
}
|
|
|
|
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(ReorderTimelinesActivity.this);
|
|
boolean singleBar = sharedpreferences.getBoolean(getString(R.string.SET_USE_SINGLE_TOPBAR), false);
|
|
if (singleBar) {
|
|
binding.titleBottom.setVisibility(View.GONE);
|
|
binding.lvReorderBottom.setVisibility(View.GONE);
|
|
binding.titleTop.setVisibility(View.GONE);
|
|
}
|
|
changes = false;
|
|
bottomChanges = false;
|
|
ReorderVM reorderVM = new ViewModelProvider(ReorderTimelinesActivity.this).get(ReorderVM.class);
|
|
reorderVM.getPinned().observe(ReorderTimelinesActivity.this, _pinned -> {
|
|
update = true;
|
|
this.pinned = _pinned;
|
|
if (this.pinned == null) {
|
|
this.pinned = new Pinned();
|
|
this.pinned.pinnedTimelines = new ArrayList<>();
|
|
update = false;
|
|
}
|
|
PinnedTimelineHelper.sortPositionAsc(this.pinned.pinnedTimelines);
|
|
reorderTabAdapter = new ReorderTabAdapter(this.pinned, ReorderTimelinesActivity.this);
|
|
ItemTouchHelper.Callback callback =
|
|
new SimpleItemTouchHelperCallback(reorderTabAdapter);
|
|
touchHelper = new ItemTouchHelper(callback);
|
|
touchHelper.attachToRecyclerView(binding.lvReorderTabs);
|
|
binding.lvReorderTabs.setAdapter(reorderTabAdapter);
|
|
LinearLayoutManager mLayoutManager = new LinearLayoutManager(ReorderTimelinesActivity.this);
|
|
binding.lvReorderTabs.setLayoutManager(mLayoutManager);
|
|
});
|
|
reorderVM.getBottomMenu().observe(ReorderTimelinesActivity.this, _bottomMenu -> {
|
|
this.bottomMenu = _bottomMenu;
|
|
if (_bottomMenu == null) {
|
|
this.bottomMenu = new BottomMenu(getApplicationContext()).defaultBottomMenu();
|
|
this.bottomMenu.bottom_menu = new ArrayList<>();
|
|
}
|
|
PinnedTimelineHelper.sortMenuItem(this.bottomMenu.bottom_menu);
|
|
reorderBottomMenuAdapter = new ReorderBottomMenuAdapter(this.bottomMenu, ReorderTimelinesActivity.this);
|
|
ItemTouchHelper.Callback callback =
|
|
new SimpleItemTouchHelperCallback(reorderBottomMenuAdapter);
|
|
touchHelper = new ItemTouchHelper(callback);
|
|
touchHelper.attachToRecyclerView(binding.lvReorderBottom);
|
|
binding.lvReorderBottom.setAdapter(reorderBottomMenuAdapter);
|
|
LinearLayoutManager mLayoutManager = new LinearLayoutManager(ReorderTimelinesActivity.this);
|
|
binding.lvReorderBottom.setLayoutManager(mLayoutManager);
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
if (item.getItemId() == android.R.id.home) {
|
|
finish();
|
|
return true;
|
|
} else if (item.getItemId() == R.id.action_add_timeline) {
|
|
addInstance();
|
|
}
|
|
return super.onOptionsItemSelected(item);
|
|
}
|
|
|
|
|
|
@Override
|
|
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
|
|
getMenuInflater().inflate(R.menu.menu_reorder, menu);
|
|
return super.onCreateOptionsMenu(menu);
|
|
}
|
|
|
|
private void addInstance() {
|
|
AlertDialog.Builder dialogBuilder = new MaterialAlertDialogBuilder(ReorderTimelinesActivity.this);
|
|
PopupSearchInstanceBinding popupSearchInstanceBinding = PopupSearchInstanceBinding.inflate(getLayoutInflater());
|
|
dialogBuilder.setView(popupSearchInstanceBinding.getRoot());
|
|
TextWatcher textWatcher = autoComplete(popupSearchInstanceBinding);
|
|
popupSearchInstanceBinding.searchInstance.addTextChangedListener(textWatcher);
|
|
|
|
popupSearchInstanceBinding.setAttachmentGroup.setOnCheckedChangeListener((group, checkedId) -> {
|
|
if (checkedId == R.id.twitter_accounts) {
|
|
popupSearchInstanceBinding.searchInstance.setHint(R.string.list_of_twitter_accounts);
|
|
popupSearchInstanceBinding.searchInstance.removeTextChangedListener(textWatcher);
|
|
} else {
|
|
popupSearchInstanceBinding.searchInstance.setHint(R.string.instance);
|
|
popupSearchInstanceBinding.searchInstance.removeTextChangedListener(textWatcher);
|
|
popupSearchInstanceBinding.searchInstance.addTextChangedListener(textWatcher);
|
|
}
|
|
});
|
|
dialogBuilder.setPositiveButton(R.string.validate, (dialog, id) -> {
|
|
String instanceName = popupSearchInstanceBinding.searchInstance.getText().toString().trim().replace("@", "");
|
|
new Thread(() -> {
|
|
String url = null;
|
|
boolean getCall = true;
|
|
RequestBody formBody = new FormBody.Builder()
|
|
.build();
|
|
if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.mastodon_instance) {
|
|
url = "https://" + instanceName + "/api/v1/timelines/public?local=true";
|
|
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.peertube_instance) {
|
|
url = "https://" + instanceName + "/api/v1/videos/";
|
|
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.pixelfed_instance) {
|
|
url = "https://" + instanceName + "/api/v1/timelines/public";
|
|
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.misskey_instance) {
|
|
url = "https://" + instanceName + "/api/notes/local-timeline";
|
|
getCall = false;
|
|
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.lemmy_instance) {
|
|
url = "https://" + instanceName + "/api/v3/post/list";
|
|
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.gnu_instance) {
|
|
url = "https://" + instanceName + "/api/statuses/public_timeline.json";
|
|
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.twitter_accounts) {
|
|
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(ReorderTimelinesActivity.this);
|
|
String nitterHost = sharedpreferences.getString(getString(R.string.SET_NITTER_HOST), getString(R.string.DEFAULT_NITTER_HOST)).toLowerCase();
|
|
url = "https://" + nitterHost + "/" + instanceName.replaceAll("[ ]+", ",").replaceAll("\\s", "") + "/with_replies/rss";
|
|
}
|
|
OkHttpClient client = new OkHttpClient.Builder()
|
|
.connectTimeout(10, TimeUnit.SECONDS)
|
|
.writeTimeout(10, TimeUnit.SECONDS)
|
|
.proxy(Helper.getProxy(getApplication().getApplicationContext()))
|
|
.readTimeout(10, TimeUnit.SECONDS).build();
|
|
Request request;
|
|
if (url != null) {
|
|
if (getCall) {
|
|
request = new Request.Builder()
|
|
.url(url)
|
|
.build();
|
|
} else {
|
|
request = new Request.Builder()
|
|
.url(url)
|
|
.post(formBody)
|
|
.build();
|
|
}
|
|
client.newCall(request).enqueue(new Callback() {
|
|
@Override
|
|
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
|
e.printStackTrace();
|
|
runOnUiThread(() -> Toasty.warning(ReorderTimelinesActivity.this, getString(R.string.toast_instance_unavailable), Toast.LENGTH_LONG).show());
|
|
}
|
|
|
|
@Override
|
|
public void onResponse(@NonNull Call call, @NonNull final Response response) {
|
|
if (response.isSuccessful()) {
|
|
runOnUiThread(() -> {
|
|
dialog.dismiss();
|
|
RemoteInstance.InstanceType instanceType = null;
|
|
if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.mastodon_instance) {
|
|
instanceType = RemoteInstance.InstanceType.MASTODON;
|
|
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.peertube_instance) {
|
|
instanceType = RemoteInstance.InstanceType.PEERTUBE;
|
|
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.pixelfed_instance) {
|
|
instanceType = RemoteInstance.InstanceType.PIXELFED;
|
|
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.misskey_instance) {
|
|
instanceType = RemoteInstance.InstanceType.MISSKEY;
|
|
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.lemmy_instance) {
|
|
instanceType = RemoteInstance.InstanceType.LEMMY;
|
|
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.gnu_instance) {
|
|
instanceType = RemoteInstance.InstanceType.GNU;
|
|
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.twitter_accounts) {
|
|
instanceType = RemoteInstance.InstanceType.NITTER;
|
|
}
|
|
RemoteInstance remoteInstance = new RemoteInstance();
|
|
remoteInstance.type = instanceType;
|
|
remoteInstance.host = instanceName;
|
|
PinnedTimeline pinnedTimeline = new PinnedTimeline();
|
|
pinnedTimeline.remoteInstance = remoteInstance;
|
|
pinnedTimeline.displayed = true;
|
|
pinnedTimeline.type = Timeline.TimeLineEnum.REMOTE;
|
|
pinnedTimeline.position = pinned.pinnedTimelines.size();
|
|
pinned.pinnedTimelines.add(pinnedTimeline);
|
|
if (pinned.user_id == null || pinned.instance == null) {
|
|
pinned.user_id = MainActivity.currentUserID;
|
|
pinned.instance = MainActivity.currentInstance;
|
|
}
|
|
if (update) {
|
|
try {
|
|
new Pinned(ReorderTimelinesActivity.this).updatePinned(pinned);
|
|
} catch (DBException e) {
|
|
e.printStackTrace();
|
|
}
|
|
} else {
|
|
try {
|
|
new Pinned(ReorderTimelinesActivity.this).insertPinned(pinned);
|
|
} catch (DBException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
reorderTabAdapter.notifyItemInserted(pinned.pinnedTimelines.size());
|
|
Bundle args = new Bundle();
|
|
args.putBoolean(Helper.RECEIVE_REDRAW_TOPBAR, true);
|
|
Intent intentBD = new Intent(Helper.BROADCAST_DATA);
|
|
new CachedBundle(ReorderTimelinesActivity.this).insertBundle(args, Helper.getCurrentAccount(ReorderTimelinesActivity.this), bundleId -> {
|
|
Bundle bundle = new Bundle();
|
|
bundle.putLong(Helper.ARG_INTENT_ID, bundleId);
|
|
intentBD.putExtras(bundle);
|
|
intentBD.setPackage(BuildConfig.APPLICATION_ID);
|
|
sendBroadcast(intentBD);
|
|
});
|
|
});
|
|
} else {
|
|
runOnUiThread(() -> Toasty.warning(ReorderTimelinesActivity.this, getString(R.string.toast_instance_unavailable), Toast.LENGTH_LONG).show());
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
runOnUiThread(() -> Toasty.warning(ReorderTimelinesActivity.this, getString(R.string.toast_instance_unavailable), Toast.LENGTH_LONG).show());
|
|
}
|
|
}).start();
|
|
});
|
|
AlertDialog alertDialog = dialogBuilder.create();
|
|
alertDialog.setOnDismissListener(dialogInterface -> {
|
|
//Hide keyboard
|
|
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
|
|
assert imm != null;
|
|
imm.hideSoftInputFromWindow(popupSearchInstanceBinding.searchInstance.getWindowToken(), 0);
|
|
});
|
|
if (alertDialog.getWindow() != null)
|
|
alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
|
alertDialog.show();
|
|
|
|
popupSearchInstanceBinding.searchInstance.setOnItemClickListener((parent, view1, position, id) -> oldSearch = parent.getItemAtPosition(position).toString().trim());
|
|
|
|
|
|
}
|
|
|
|
private TextWatcher autoComplete(PopupSearchInstanceBinding popupSearchInstanceBinding) {
|
|
return new TextWatcher() {
|
|
@Override
|
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
|
}
|
|
|
|
@Override
|
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void afterTextChanged(Editable s) {
|
|
|
|
if (s.length() > 2 && !searchInstanceRunning) {
|
|
String query = s.toString().trim();
|
|
if (query.startsWith("http://")) {
|
|
query = query.replace("http://", "");
|
|
}
|
|
if (query.startsWith("https://")) {
|
|
query = query.replace("https://", "");
|
|
}
|
|
if (oldSearch == null || !oldSearch.equals(s.toString().trim())) {
|
|
searchInstanceRunning = true;
|
|
InstanceSocialVM instanceSocialVM = new ViewModelProvider(ReorderTimelinesActivity.this).get(InstanceSocialVM.class);
|
|
instanceSocialVM.getInstances(query).observe(ReorderTimelinesActivity.this, instanceSocialList -> {
|
|
popupSearchInstanceBinding.searchInstance.setAdapter(null);
|
|
String[] instances = new String[instanceSocialList.instances.size()];
|
|
int j = 0;
|
|
for (InstanceSocial.Instance instance : instanceSocialList.instances) {
|
|
instances[j] = instance.name;
|
|
j++;
|
|
}
|
|
ArrayAdapter<String> arrayAdapter =
|
|
new ArrayAdapter<>(ReorderTimelinesActivity.this, android.R.layout.simple_list_item_1, instances);
|
|
popupSearchInstanceBinding.searchInstance.setAdapter(arrayAdapter);
|
|
if (popupSearchInstanceBinding.searchInstance.hasFocus() && !isFinishing())
|
|
popupSearchInstanceBinding.searchInstance.showDropDown();
|
|
if (oldSearch != null && oldSearch.equals(popupSearchInstanceBinding.searchInstance.getText().toString())) {
|
|
popupSearchInstanceBinding.searchInstance.dismissDropDown();
|
|
}
|
|
|
|
oldSearch = s.toString().trim();
|
|
searchInstanceRunning = false;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
@Override
|
|
protected void onPause() {
|
|
super.onPause();
|
|
if (changes) {
|
|
//Update menu
|
|
Bundle args = new Bundle();
|
|
args.putBoolean(Helper.RECEIVE_REDRAW_TOPBAR, true);
|
|
Intent intentBD = new Intent(Helper.BROADCAST_DATA);
|
|
new CachedBundle(ReorderTimelinesActivity.this).insertBundle(args, Helper.getCurrentAccount(ReorderTimelinesActivity.this), bundleId -> {
|
|
Bundle bundle = new Bundle();
|
|
bundle.putLong(Helper.ARG_INTENT_ID, bundleId);
|
|
intentBD.putExtras(bundle);
|
|
intentBD.setPackage(BuildConfig.APPLICATION_ID);
|
|
sendBroadcast(intentBD);
|
|
});
|
|
|
|
}
|
|
if (bottomChanges) {
|
|
Bundle args = new Bundle();
|
|
args.putBoolean(Helper.RECEIVE_REDRAW_BOTTOM, true);
|
|
Intent intentBD = new Intent(Helper.BROADCAST_DATA);
|
|
new CachedBundle(ReorderTimelinesActivity.this).insertBundle(args, Helper.getCurrentAccount(ReorderTimelinesActivity.this), bundleId -> {
|
|
Bundle bundle = new Bundle();
|
|
bundle.putLong(Helper.ARG_INTENT_ID, bundleId);
|
|
intentBD.putExtras(bundle);
|
|
intentBD.setPackage(BuildConfig.APPLICATION_ID);
|
|
sendBroadcast(intentBD);
|
|
});
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
|
|
touchHelper.startDrag(viewHolder);
|
|
}
|
|
|
|
|
|
@Override
|
|
public void onStop() {
|
|
super.onStop();
|
|
}
|
|
|
|
|
|
}
|