mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-08 07:57:28 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
700711f5f3
@ -111,7 +111,6 @@ dependencies {
|
|||||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
||||||
|
|
||||||
implementation 'org.apache.commons:commons-imaging:1.0-alpha2'
|
implementation 'org.apache.commons:commons-imaging:1.0-alpha2'
|
||||||
implementation 'com.ibm.icu:icu4j:68.1'
|
|
||||||
implementation 'com.github.ammargitham:uCrop:2.3-native-beta-2'
|
implementation 'com.github.ammargitham:uCrop:2.3-native-beta-2'
|
||||||
implementation 'com.github.ammargitham:android-gpuimage:2.1.1-beta4'
|
implementation 'com.github.ammargitham:android-gpuimage:2.1.1-beta4'
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme.Light.White"
|
android:theme="@style/AppTheme.Launcher"
|
||||||
tools:ignore="UnusedAttribute">
|
tools:ignore="UnusedAttribute">
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.MainActivity"
|
android:name=".activities.MainActivity"
|
||||||
|
@ -72,7 +72,6 @@ import awais.instagrabber.interfaces.FetchListener;
|
|||||||
import awais.instagrabber.models.IntentModel;
|
import awais.instagrabber.models.IntentModel;
|
||||||
import awais.instagrabber.models.SuggestionModel;
|
import awais.instagrabber.models.SuggestionModel;
|
||||||
import awais.instagrabber.models.enums.SuggestionType;
|
import awais.instagrabber.models.enums.SuggestionType;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
|
||||||
import awais.instagrabber.services.ActivityCheckerService;
|
import awais.instagrabber.services.ActivityCheckerService;
|
||||||
import awais.instagrabber.services.DMSyncAlarmReceiver;
|
import awais.instagrabber.services.DMSyncAlarmReceiver;
|
||||||
import awais.instagrabber.utils.AppExecutors;
|
import awais.instagrabber.utils.AppExecutors;
|
||||||
@ -251,7 +250,17 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
if (isTaskRoot() && isBackStackEmpty) {
|
int currentNavControllerBackStack = 2;
|
||||||
|
if (currentNavControllerLiveData != null) {
|
||||||
|
final NavController navController = currentNavControllerLiveData.getValue();
|
||||||
|
if (navController != null) {
|
||||||
|
@SuppressLint("RestrictedApi") final Deque<NavBackStackEntry> backStack = navController.getBackStack();
|
||||||
|
if (backStack != null) {
|
||||||
|
currentNavControllerBackStack = backStack.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isTaskRoot() && isBackStackEmpty && currentNavControllerBackStack == 2) {
|
||||||
finishAfterTransition();
|
finishAfterTransition();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -577,10 +586,10 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
private void showThread(@NonNull final Intent intent) {
|
private void showThread(@NonNull final Intent intent) {
|
||||||
final String threadId = intent.getStringExtra(Constants.DM_THREAD_ACTION_EXTRA_THREAD_ID);
|
final String threadId = intent.getStringExtra(Constants.DM_THREAD_ACTION_EXTRA_THREAD_ID);
|
||||||
final String threadTitle = intent.getStringExtra(Constants.DM_THREAD_ACTION_EXTRA_THREAD_TITLE);
|
final String threadTitle = intent.getStringExtra(Constants.DM_THREAD_ACTION_EXTRA_THREAD_TITLE);
|
||||||
navigateToThread(threadId, threadTitle, null);
|
navigateToThread(threadId, threadTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void navigateToThread(final String threadId, final String threadTitle, final DirectThread backup) {
|
public void navigateToThread(final String threadId, final String threadTitle) {
|
||||||
if (threadId == null || threadTitle == null) return;
|
if (threadId == null || threadTitle == null) return;
|
||||||
currentNavControllerLiveData.observe(this, new Observer<NavController>() {
|
currentNavControllerLiveData.observe(this, new Observer<NavController>() {
|
||||||
@Override
|
@Override
|
||||||
@ -594,7 +603,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
// need handler.post() to wait for the fragment manager to be ready to navigate
|
// need handler.post() to wait for the fragment manager to be ready to navigate
|
||||||
new Handler().post(() -> {
|
new Handler().post(() -> {
|
||||||
final DirectMessageInboxFragmentDirections.ActionInboxToThread action = DirectMessageInboxFragmentDirections
|
final DirectMessageInboxFragmentDirections.ActionInboxToThread action = DirectMessageInboxFragmentDirections
|
||||||
.actionInboxToThread(threadId, threadTitle, backup);
|
.actionInboxToThread(threadId, threadTitle);
|
||||||
navController.navigate(action);
|
navController.navigate(action);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@ -607,7 +616,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
@Nullable final Bundle arguments) {
|
@Nullable final Bundle arguments) {
|
||||||
if (destination.getId() == R.id.directMessagesInboxFragment) {
|
if (destination.getId() == R.id.directMessagesInboxFragment) {
|
||||||
final DirectMessageInboxFragmentDirections.ActionInboxToThread action = DirectMessageInboxFragmentDirections
|
final DirectMessageInboxFragmentDirections.ActionInboxToThread action = DirectMessageInboxFragmentDirections
|
||||||
.actionInboxToThread(threadId, threadTitle, backup);
|
.actionInboxToThread(threadId, threadTitle);
|
||||||
controller.navigate(action);
|
controller.navigate(action);
|
||||||
controller.removeOnDestinationChangedListener(this);
|
controller.removeOnDestinationChangedListener(this);
|
||||||
}
|
}
|
||||||
|
@ -12,4 +12,7 @@ public class SliderCallbackAdapter implements SliderItemsAdapter.SliderCallback
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerPause(final int position) {}
|
public void onPlayerPause(final int position) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayerRelease(final int position) {}
|
||||||
}
|
}
|
||||||
|
@ -148,5 +148,7 @@ public final class SliderItemsAdapter extends ListAdapter<Media, SliderItemViewH
|
|||||||
void onPlayerPlay(int position);
|
void onPlayerPlay(int position);
|
||||||
|
|
||||||
void onPlayerPause(int position);
|
void onPlayerPause(int position);
|
||||||
|
|
||||||
|
void onPlayerRelease(int position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,13 @@ public class SliderVideoViewHolder extends SliderItemViewHolder {
|
|||||||
sliderCallback.onPlayerPause(position);
|
sliderCallback.onPlayerPause(position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRelease() {
|
||||||
|
if (sliderCallback != null) {
|
||||||
|
sliderCallback.onPlayerRelease(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
final float aspectRatio = (float) media.getOriginalWidth() / media.getOriginalHeight();
|
final float aspectRatio = (float) media.getOriginalWidth() / media.getOriginalHeight();
|
||||||
String videoUrl = null;
|
String videoUrl = null;
|
||||||
|
@ -15,4 +15,7 @@ public class VideoPlayerCallbackAdapter implements VideoPlayerViewHelper.VideoPl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {}
|
public void onPause() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRelease() {}
|
||||||
}
|
}
|
||||||
|
@ -359,6 +359,9 @@ public class VideoPlayerViewHelper implements Player.EventListener {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
public void releasePlayer() {
|
public void releasePlayer() {
|
||||||
|
if (videoPlayerCallback != null) {
|
||||||
|
videoPlayerCallback.onRelease();
|
||||||
|
}
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
player.release();
|
player.release();
|
||||||
player = null;
|
player = null;
|
||||||
@ -453,5 +456,7 @@ public class VideoPlayerViewHelper implements Player.EventListener {
|
|||||||
void onPlay();
|
void onPlay();
|
||||||
|
|
||||||
void onPause();
|
void onPause();
|
||||||
|
|
||||||
|
void onRelease();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,35 +16,6 @@ public class EmojiCategory {
|
|||||||
|
|
||||||
public EmojiCategory(final EmojiCategoryType type) {
|
public EmojiCategory(final EmojiCategoryType type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
switch (type) {
|
|
||||||
case SMILEYS_AND_EMOTION:
|
|
||||||
drawableRes = R.drawable.ic_round_emoji_emotions_24;
|
|
||||||
break;
|
|
||||||
case ANIMALS_AND_NATURE:
|
|
||||||
drawableRes = R.drawable.ic_round_emoji_nature_24;
|
|
||||||
break;
|
|
||||||
case FOOD_AND_DRINK:
|
|
||||||
drawableRes = R.drawable.ic_round_emoji_food_beverage_24;
|
|
||||||
break;
|
|
||||||
case TRAVEL_AND_PLACES:
|
|
||||||
drawableRes = R.drawable.ic_round_emoji_transportation_24;
|
|
||||||
break;
|
|
||||||
case ACTIVITIES:
|
|
||||||
drawableRes = R.drawable.ic_round_emoji_events_24;
|
|
||||||
break;
|
|
||||||
case OBJECTS:
|
|
||||||
drawableRes = R.drawable.ic_round_emoji_objects_24;
|
|
||||||
break;
|
|
||||||
case SYMBOLS:
|
|
||||||
drawableRes = R.drawable.ic_round_emoji_symbols_24;
|
|
||||||
break;
|
|
||||||
case FLAGS:
|
|
||||||
drawableRes = R.drawable.ic_round_emoji_flags_24;
|
|
||||||
break;
|
|
||||||
case OTHERS:
|
|
||||||
drawableRes = R.drawable.ic_round_unknown_24;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmojiCategoryType getType() {
|
public EmojiCategoryType getType() {
|
||||||
@ -56,6 +27,37 @@ public class EmojiCategory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getDrawableRes() {
|
public int getDrawableRes() {
|
||||||
|
if (drawableRes == 0) {
|
||||||
|
switch (type) {
|
||||||
|
case SMILEYS_AND_EMOTION:
|
||||||
|
drawableRes = R.drawable.ic_round_emoji_emotions_24;
|
||||||
|
break;
|
||||||
|
case ANIMALS_AND_NATURE:
|
||||||
|
drawableRes = R.drawable.ic_round_emoji_nature_24;
|
||||||
|
break;
|
||||||
|
case FOOD_AND_DRINK:
|
||||||
|
drawableRes = R.drawable.ic_round_emoji_food_beverage_24;
|
||||||
|
break;
|
||||||
|
case TRAVEL_AND_PLACES:
|
||||||
|
drawableRes = R.drawable.ic_round_emoji_transportation_24;
|
||||||
|
break;
|
||||||
|
case ACTIVITIES:
|
||||||
|
drawableRes = R.drawable.ic_round_emoji_events_24;
|
||||||
|
break;
|
||||||
|
case OBJECTS:
|
||||||
|
drawableRes = R.drawable.ic_round_emoji_objects_24;
|
||||||
|
break;
|
||||||
|
case SYMBOLS:
|
||||||
|
drawableRes = R.drawable.ic_round_emoji_symbols_24;
|
||||||
|
break;
|
||||||
|
case FLAGS:
|
||||||
|
drawableRes = R.drawable.ic_round_emoji_flags_24;
|
||||||
|
break;
|
||||||
|
case OTHERS:
|
||||||
|
drawableRes = R.drawable.ic_round_unknown_24;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return drawableRes;
|
return drawableRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ import androidx.core.content.PermissionChecker;
|
|||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
import androidx.core.widget.NestedScrollView;
|
import androidx.core.widget.NestedScrollView;
|
||||||
import androidx.fragment.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.Observer;
|
||||||
@ -1062,15 +1063,28 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerPlay(final int position) {
|
public void onPlayerPlay(final int position) {
|
||||||
|
final FragmentActivity activity = getActivity();
|
||||||
|
if (activity == null) return;
|
||||||
|
Utils.enabledKeepScreenOn(activity);
|
||||||
if (!detailsVisible || hasBeenToggled) return;
|
if (!detailsVisible || hasBeenToggled) return;
|
||||||
showPlayerControls();
|
showPlayerControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerPause(final int position) {
|
public void onPlayerPause(final int position) {
|
||||||
|
final FragmentActivity activity = getActivity();
|
||||||
|
if (activity == null) return;
|
||||||
|
Utils.disableKeepScreenOn(activity);
|
||||||
if (detailsVisible || hasBeenToggled) return;
|
if (detailsVisible || hasBeenToggled) return;
|
||||||
toggleDetails();
|
toggleDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayerRelease(final int position) {
|
||||||
|
final FragmentActivity activity = getActivity();
|
||||||
|
if (activity == null) return;
|
||||||
|
Utils.disableKeepScreenOn(activity);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
binding.sliderParent.setAdapter(sliderItemsAdapter);
|
binding.sliderParent.setAdapter(sliderItemsAdapter);
|
||||||
if (sliderPosition >= 0 && sliderPosition < media.getCarouselMedia().size()) {
|
if (sliderPosition >= 0 && sliderPosition < media.getCarouselMedia().size()) {
|
||||||
@ -1206,7 +1220,7 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerViewLoaded() {
|
public void onPlayerViewLoaded() {
|
||||||
binding.playerControls.getRoot().setVisibility(View.VISIBLE);
|
// binding.playerControls.getRoot().setVisibility(View.VISIBLE);
|
||||||
final ViewGroup.LayoutParams layoutParams = binding.videoPost.playerView.getLayoutParams();
|
final ViewGroup.LayoutParams layoutParams = binding.videoPost.playerView.getLayoutParams();
|
||||||
final int requiredWidth = Utils.displayMetrics.widthPixels;
|
final int requiredWidth = Utils.displayMetrics.widthPixels;
|
||||||
final int resultingHeight = NumberUtils
|
final int resultingHeight = NumberUtils
|
||||||
@ -1218,10 +1232,27 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlay() {
|
public void onPlay() {
|
||||||
|
final FragmentActivity activity = getActivity();
|
||||||
|
if (activity == null) return;
|
||||||
|
Utils.enabledKeepScreenOn(activity);
|
||||||
if (detailsVisible) {
|
if (detailsVisible) {
|
||||||
new Handler().postDelayed(() -> toggleDetails(), DETAILS_HIDE_DELAY_MILLIS);
|
new Handler().postDelayed(() -> toggleDetails(), DETAILS_HIDE_DELAY_MILLIS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
final FragmentActivity activity = getActivity();
|
||||||
|
if (activity == null) return;
|
||||||
|
Utils.disableKeepScreenOn(activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRelease() {
|
||||||
|
final FragmentActivity activity = getActivity();
|
||||||
|
if (activity == null) return;
|
||||||
|
Utils.disableKeepScreenOn(activity);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
final float aspectRatio = (float) media.getOriginalWidth() / media.getOriginalHeight();
|
final float aspectRatio = (float) media.getOriginalWidth() / media.getOriginalHeight();
|
||||||
String videoUrl = null;
|
String videoUrl = null;
|
||||||
|
@ -257,7 +257,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
|||||||
navigating = true;
|
navigating = true;
|
||||||
if (isAdded()) {
|
if (isAdded()) {
|
||||||
final DirectMessageInboxFragmentDirections.ActionInboxToThread directions = DirectMessageInboxFragmentDirections
|
final DirectMessageInboxFragmentDirections.ActionInboxToThread directions = DirectMessageInboxFragmentDirections
|
||||||
.actionInboxToThread(thread.getThreadId(), thread.getThreadTitle(), thread);
|
.actionInboxToThread(thread.getThreadId(), thread.getThreadTitle());
|
||||||
NavHostFragment.findNavController(this).navigate(directions);
|
NavHostFragment.findNavController(this).navigate(directions);
|
||||||
}
|
}
|
||||||
navigating = false;
|
navigating = false;
|
||||||
|
@ -81,7 +81,6 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
final AppStateViewModel appStateViewModel = new ViewModelProvider(fragmentActivity).get(AppStateViewModel.class);
|
final AppStateViewModel appStateViewModel = new ViewModelProvider(fragmentActivity).get(AppStateViewModel.class);
|
||||||
viewModel = new ViewModelProvider(this, new DirectSettingsViewModelFactory(fragmentActivity.getApplication(),
|
viewModel = new ViewModelProvider(this, new DirectSettingsViewModelFactory(fragmentActivity.getApplication(),
|
||||||
args.getThreadId(),
|
args.getThreadId(),
|
||||||
args.getBackup(),
|
|
||||||
args.getPending(),
|
args.getPending(),
|
||||||
appStateViewModel.getCurrentUser()))
|
appStateViewModel.getCurrentUser()))
|
||||||
.get(DirectSettingsViewModel.class);
|
.get(DirectSettingsViewModel.class);
|
||||||
@ -348,15 +347,15 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
usersAdapter = new DirectUsersAdapter(
|
usersAdapter = new DirectUsersAdapter(
|
||||||
inviter != null ? inviter.getPk() : -1,
|
inviter != null ? inviter.getPk() : -1,
|
||||||
(position, user, selected) -> {
|
(position, user, selected) -> {
|
||||||
if (!TextUtils.isEmpty(user.getFbId())) {
|
if (TextUtils.isEmpty(user.getUsername()) && !TextUtils.isEmpty(user.getFbId())) {
|
||||||
Utils.openURL(context, "https://facebook.com/" + user.getFbId());
|
Utils.openURL(context, "https://facebook.com/" + user.getFbId());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
if (TextUtils.isEmpty(user.getUsername())) return;
|
||||||
final ProfileNavGraphDirections.ActionGlobalProfileFragment directions = ProfileNavGraphDirections
|
final ProfileNavGraphDirections.ActionGlobalProfileFragment directions = ProfileNavGraphDirections
|
||||||
.actionGlobalProfileFragment()
|
.actionGlobalProfileFragment()
|
||||||
.setUsername("@" + user.getUsername());
|
.setUsername("@" + user.getUsername());
|
||||||
NavHostFragment.findNavController(this).navigate(directions);
|
NavHostFragment.findNavController(this).navigate(directions);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
(position, user) -> {
|
(position, user) -> {
|
||||||
final ArrayList<Option<String>> options = viewModel.createUserOptions(user);
|
final ArrayList<Option<String>> options = viewModel.createUserOptions(user);
|
||||||
|
@ -100,6 +100,7 @@ import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
|||||||
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient;
|
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient;
|
||||||
import awais.instagrabber.utils.AppExecutors;
|
import awais.instagrabber.utils.AppExecutors;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
|
import awais.instagrabber.utils.DMUtils;
|
||||||
import awais.instagrabber.utils.DownloadUtils;
|
import awais.instagrabber.utils.DownloadUtils;
|
||||||
import awais.instagrabber.utils.PermissionUtils;
|
import awais.instagrabber.utils.PermissionUtils;
|
||||||
import awais.instagrabber.utils.ResponseBodyUtils;
|
import awais.instagrabber.utils.ResponseBodyUtils;
|
||||||
@ -317,6 +318,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
backStackSavedStateResultLiveData.postValue(null);
|
backStackSavedStateResultLiveData.postValue(null);
|
||||||
};
|
};
|
||||||
private final MutableLiveData<Integer> inputLength = new MutableLiveData<>(0);
|
private final MutableLiveData<Integer> inputLength = new MutableLiveData<>(0);
|
||||||
|
private MenuItem markAsSeenMenuItem;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
@ -329,7 +331,6 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
final DirectMessageThreadFragmentArgs fragmentArgs = DirectMessageThreadFragmentArgs.fromBundle(arguments);
|
final DirectMessageThreadFragmentArgs fragmentArgs = DirectMessageThreadFragmentArgs.fromBundle(arguments);
|
||||||
viewModel = new ViewModelProvider(this, new DirectThreadViewModelFactory(fragmentActivity.getApplication(),
|
viewModel = new ViewModelProvider(this, new DirectThreadViewModelFactory(fragmentActivity.getApplication(),
|
||||||
fragmentArgs.getThreadId(),
|
fragmentArgs.getThreadId(),
|
||||||
fragmentArgs.getBackup(),
|
|
||||||
fragmentArgs.getPending(),
|
fragmentArgs.getPending(),
|
||||||
appStateViewModel.getCurrentUser()))
|
appStateViewModel.getCurrentUser()))
|
||||||
.get(DirectThreadViewModel.class);
|
.get(DirectThreadViewModel.class);
|
||||||
@ -368,9 +369,13 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) {
|
public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) {
|
||||||
inflater.inflate(R.menu.dm_thread_menu, menu);
|
inflater.inflate(R.menu.dm_thread_menu, menu);
|
||||||
final MenuItem markAsSeenMenuItem = menu.findItem(R.id.mark_as_seen);
|
markAsSeenMenuItem = menu.findItem(R.id.mark_as_seen);
|
||||||
if (markAsSeenMenuItem != null) {
|
if (markAsSeenMenuItem != null) {
|
||||||
markAsSeenMenuItem.setVisible(false);
|
if (autoMarkAsSeen) {
|
||||||
|
markAsSeenMenuItem.setVisible(false);
|
||||||
|
} else {
|
||||||
|
markAsSeenMenuItem.setEnabled(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,15 +384,14 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
final int itemId = item.getItemId();
|
final int itemId = item.getItemId();
|
||||||
if (itemId == R.id.info) {
|
if (itemId == R.id.info) {
|
||||||
final DirectMessageThreadFragmentDirections.ActionThreadToSettings directions = DirectMessageThreadFragmentDirections
|
final DirectMessageThreadFragmentDirections.ActionThreadToSettings directions = DirectMessageThreadFragmentDirections
|
||||||
.actionThreadToSettings(viewModel.getThreadId(), null, null);
|
.actionThreadToSettings(viewModel.getThreadId(), null);
|
||||||
final Boolean pending = viewModel.isPending().getValue();
|
final Boolean pending = viewModel.isPending().getValue();
|
||||||
directions.setPending(pending == null ? false : pending);
|
directions.setPending(pending == null ? false : pending);
|
||||||
NavHostFragment.findNavController(this).navigate(directions);
|
NavHostFragment.findNavController(this).navigate(directions);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (itemId == R.id.mark_as_seen) {
|
if (itemId == R.id.mark_as_seen) {
|
||||||
// new ThreadAction().execute("seen", lastMessage);
|
handleMarkAsSeen(item);
|
||||||
item.setVisible(false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (itemId == R.id.refresh && viewModel != null) {
|
if (itemId == R.id.refresh && viewModel != null) {
|
||||||
@ -397,6 +401,40 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleMarkAsSeen(@NonNull final MenuItem item) {
|
||||||
|
final LiveData<Resource<Object>> resourceLiveData = viewModel.markAsSeen();
|
||||||
|
resourceLiveData.observe(getViewLifecycleOwner(), new Observer<Resource<Object>>() {
|
||||||
|
@Override
|
||||||
|
public void onChanged(final Resource<Object> resource) {
|
||||||
|
try {
|
||||||
|
if (resource == null) return;
|
||||||
|
final Context context = getContext();
|
||||||
|
if (context == null) return;
|
||||||
|
switch (resource.status) {
|
||||||
|
case SUCCESS:
|
||||||
|
Toast.makeText(context, R.string.marked_as_seen, Toast.LENGTH_SHORT).show();
|
||||||
|
case LOADING:
|
||||||
|
item.setEnabled(false);
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
item.setEnabled(true);
|
||||||
|
if (resource.message != null) {
|
||||||
|
Snackbar.make(context, binding.getRoot(), resource.message, Snackbar.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (resource.resId != 0) {
|
||||||
|
Snackbar.make(binding.getRoot(), resource.resId, Snackbar.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
resourceLiveData.removeObserver(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
@ -464,6 +502,12 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
viewModel.deleteThreadIfRequired();
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("UnsafeExperimentalUsageError")
|
@SuppressLint("UnsafeExperimentalUsageError")
|
||||||
private void cleanup() {
|
private void cleanup() {
|
||||||
if (prevTitleRunnable != null) {
|
if (prevTitleRunnable != null) {
|
||||||
@ -903,9 +947,15 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void submitItemsToAdapter(final List<DirectItem> items) {
|
private void submitItemsToAdapter(final List<DirectItem> items) {
|
||||||
if (autoMarkAsSeen) {
|
binding.chats.post(() -> {
|
||||||
binding.chats.post(() -> viewModel.markAsSeen());
|
if (autoMarkAsSeen) {
|
||||||
}
|
viewModel.markAsSeen();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final DirectThread thread = threadLiveData.getValue();
|
||||||
|
if (thread == null) return;
|
||||||
|
markAsSeenMenuItem.setEnabled(!DMUtils.isRead(thread));
|
||||||
|
});
|
||||||
if (itemsAdapter == null) return;
|
if (itemsAdapter == null) return;
|
||||||
itemsAdapter.submitList(items, () -> {
|
itemsAdapter.submitList(items, () -> {
|
||||||
itemOrHeaders = itemsAdapter.getList();
|
itemOrHeaders = itemsAdapter.getList();
|
||||||
|
@ -163,7 +163,7 @@ public class DirectPendingInboxFragment extends Fragment implements SwipeRefresh
|
|||||||
navigating = true;
|
navigating = true;
|
||||||
if (isAdded()) {
|
if (isAdded()) {
|
||||||
final DirectPendingInboxFragmentDirections.ActionPendingInboxToThread directions = DirectPendingInboxFragmentDirections
|
final DirectPendingInboxFragmentDirections.ActionPendingInboxToThread directions = DirectPendingInboxFragmentDirections
|
||||||
.actionPendingInboxToThread(thread.getThreadId(), thread.getThreadTitle(), thread);
|
.actionPendingInboxToThread(thread.getThreadId(), thread.getThreadTitle());
|
||||||
directions.setPending(true);
|
directions.setPending(true);
|
||||||
NavHostFragment.findNavController(this).navigate(directions);
|
NavHostFragment.findNavController(this).navigate(directions);
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,8 @@ import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
|
|||||||
import awais.instagrabber.dialogs.ProfilePicDialogFragment;
|
import awais.instagrabber.dialogs.ProfilePicDialogFragment;
|
||||||
import awais.instagrabber.fragments.PostViewV2Fragment;
|
import awais.instagrabber.fragments.PostViewV2Fragment;
|
||||||
import awais.instagrabber.interfaces.FetchListener;
|
import awais.instagrabber.interfaces.FetchListener;
|
||||||
|
import awais.instagrabber.managers.DirectMessagesManager;
|
||||||
|
import awais.instagrabber.managers.InboxManager;
|
||||||
import awais.instagrabber.models.HighlightModel;
|
import awais.instagrabber.models.HighlightModel;
|
||||||
import awais.instagrabber.models.PostsLayoutPreferences;
|
import awais.instagrabber.models.PostsLayoutPreferences;
|
||||||
import awais.instagrabber.models.StoryModel;
|
import awais.instagrabber.models.StoryModel;
|
||||||
@ -590,8 +592,11 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
|
|
||||||
private void fetchProfileDetails() {
|
private void fetchProfileDetails() {
|
||||||
accountIsUpdated = false;
|
accountIsUpdated = false;
|
||||||
new ProfileFetcher(TextUtils.isEmpty(username) ? null : username.trim().substring(1),
|
String usernameTemp = username.trim();
|
||||||
myId, isLoggedIn, new FetchListener<User>() {
|
if (usernameTemp.startsWith("@")) {
|
||||||
|
usernameTemp = usernameTemp.substring(1);
|
||||||
|
}
|
||||||
|
new ProfileFetcher(TextUtils.isEmpty(username) ? null : usernameTemp, myId, isLoggedIn, new FetchListener<User>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResult(final User user) {
|
public void onResult(final User user) {
|
||||||
if (getContext() == null) return;
|
if (getContext() == null) return;
|
||||||
@ -612,7 +617,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
isLoggedIn ? R.string.error_loading_profile_loggedin : R.string.error_loading_profile,
|
isLoggedIn ? R.string.error_loading_profile_loggedin : R.string.error_loading_profile,
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
else Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show();
|
else Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||||
} catch (final Throwable e) {}
|
} catch (final Throwable ignored) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
@ -1073,7 +1078,12 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
profileDetailsBinding.btnDM.setEnabled(true);
|
profileDetailsBinding.btnDM.setEnabled(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fragmentActivity.navigateToThread(thread.getThreadId(), profileModel.getUsername(), thread);
|
final InboxManager inboxManager = DirectMessagesManager.getInstance().getInboxManager();
|
||||||
|
if (!inboxManager.containsThread(thread.getThreadId())) {
|
||||||
|
thread.setTemp(true);
|
||||||
|
inboxManager.addThread(thread, 0);
|
||||||
|
}
|
||||||
|
fragmentActivity.navigateToThread(thread.getThreadId(), profileModel.getUsername());
|
||||||
profileDetailsBinding.btnDM.setEnabled(true);
|
profileDetailsBinding.btnDM.setEnabled(true);
|
||||||
}).execute();
|
}).execute();
|
||||||
});
|
});
|
||||||
|
@ -74,9 +74,8 @@ public final class DirectMessagesManager {
|
|||||||
|
|
||||||
public ThreadManager getThreadManager(@NonNull final String threadId,
|
public ThreadManager getThreadManager(@NonNull final String threadId,
|
||||||
final boolean pending,
|
final boolean pending,
|
||||||
final DirectThread backup,
|
|
||||||
@NonNull final User currentUser,
|
@NonNull final User currentUser,
|
||||||
@NonNull final ContentResolver contentResolver) {
|
@NonNull final ContentResolver contentResolver) {
|
||||||
return ThreadManager.getInstance(threadId, pending, backup, currentUser, contentResolver);
|
return ThreadManager.getInstance(threadId, pending, currentUser, contentResolver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import java.util.Collections;
|
|||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -357,4 +358,15 @@ public final class InboxManager {
|
|||||||
public void setPendingRequestsTotal(final int total) {
|
public void setPendingRequestsTotal(final int total) {
|
||||||
pendingRequestsTotal.postValue(total);
|
pendingRequestsTotal.postValue(total);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean containsThread(final String threadId) {
|
||||||
|
if (threadId == null) return false;
|
||||||
|
synchronized (this.inbox) {
|
||||||
|
final DirectInbox currentDirectInbox = getCurrentDirectInbox();
|
||||||
|
if (currentDirectInbox == null) return false;
|
||||||
|
final List<DirectThread> threads = currentDirectInbox.getThreads();
|
||||||
|
if (threads == null) return false;
|
||||||
|
return threads.stream().anyMatch(thread -> Objects.equals(thread.getThreadId(), threadId));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,6 @@ public final class ThreadManager {
|
|||||||
|
|
||||||
public static ThreadManager getInstance(@NonNull final String threadId,
|
public static ThreadManager getInstance(@NonNull final String threadId,
|
||||||
final boolean pending,
|
final boolean pending,
|
||||||
final DirectThread backup,
|
|
||||||
@NonNull final User currentUser,
|
@NonNull final User currentUser,
|
||||||
@NonNull final ContentResolver contentResolver) {
|
@NonNull final ContentResolver contentResolver) {
|
||||||
ThreadManager instance = INSTANCE_MAP.get(threadId);
|
ThreadManager instance = INSTANCE_MAP.get(threadId);
|
||||||
@ -131,7 +130,7 @@ public final class ThreadManager {
|
|||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
instance = INSTANCE_MAP.get(threadId);
|
instance = INSTANCE_MAP.get(threadId);
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
instance = new ThreadManager(threadId, pending, backup, currentUser, contentResolver);
|
instance = new ThreadManager(threadId, pending, currentUser, contentResolver);
|
||||||
INSTANCE_MAP.put(threadId, instance);
|
INSTANCE_MAP.put(threadId, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,7 +144,6 @@ public final class ThreadManager {
|
|||||||
|
|
||||||
private ThreadManager(@NonNull final String threadId,
|
private ThreadManager(@NonNull final String threadId,
|
||||||
final boolean pending,
|
final boolean pending,
|
||||||
final DirectThread backup,
|
|
||||||
@NonNull final User currentUser,
|
@NonNull final User currentUser,
|
||||||
@NonNull final ContentResolver contentResolver) {
|
@NonNull final ContentResolver contentResolver) {
|
||||||
final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance();
|
final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance();
|
||||||
@ -164,17 +162,17 @@ public final class ThreadManager {
|
|||||||
service = DirectMessagesService.getInstance(csrfToken, viewerId, deviceUuid);
|
service = DirectMessagesService.getInstance(csrfToken, viewerId, deviceUuid);
|
||||||
mediaService = MediaService.getInstance(deviceUuid, csrfToken, viewerId);
|
mediaService = MediaService.getInstance(deviceUuid, csrfToken, viewerId);
|
||||||
friendshipService = FriendshipService.getInstance(deviceUuid, csrfToken, viewerId);
|
friendshipService = FriendshipService.getInstance(deviceUuid, csrfToken, viewerId);
|
||||||
setupTransformations(backup);
|
setupTransformations();
|
||||||
// fetchChats();
|
// fetchChats();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void moveFromPending() {
|
public void moveFromPending() {
|
||||||
final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance();
|
final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance();
|
||||||
this.inboxManager = messagesManager.getInboxManager();
|
this.inboxManager = messagesManager.getInboxManager();
|
||||||
setupTransformations(null);
|
setupTransformations();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupTransformations(final DirectThread backup) {
|
private void setupTransformations() {
|
||||||
// Transformations
|
// Transformations
|
||||||
thread = distinctUntilChanged(map(inboxManager.getInbox(), inboxResource -> {
|
thread = distinctUntilChanged(map(inboxManager.getInbox(), inboxResource -> {
|
||||||
if (inboxResource == null) {
|
if (inboxResource == null) {
|
||||||
@ -188,7 +186,7 @@ public final class ThreadManager {
|
|||||||
final DirectThread thread = threads.stream()
|
final DirectThread thread = threads.stream()
|
||||||
.filter(t -> t.getThreadId().equals(threadId))
|
.filter(t -> t.getThreadId().equals(threadId))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(backup);
|
.orElse(null);
|
||||||
if (thread != null) {
|
if (thread != null) {
|
||||||
cursor = thread.getOldestCursor();
|
cursor = thread.getOldestCursor();
|
||||||
hasOlder = thread.hasOlder();
|
hasOlder = thread.hasOlder();
|
||||||
@ -1799,18 +1797,23 @@ public final class ThreadManager {
|
|||||||
return inviter;
|
return inviter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void markAsSeen(@NonNull final DirectItem directItem) {
|
public LiveData<Resource<Object>> markAsSeen(@NonNull final DirectItem directItem) {
|
||||||
|
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
||||||
|
data.postValue(Resource.loading(null));
|
||||||
final Call<DirectItemSeenResponse> request = service.markAsSeen(threadId, directItem);
|
final Call<DirectItemSeenResponse> request = service.markAsSeen(threadId, directItem);
|
||||||
request.enqueue(new Callback<DirectItemSeenResponse>() {
|
request.enqueue(new Callback<DirectItemSeenResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(@NonNull final Call<DirectItemSeenResponse> call,
|
public void onResponse(@NonNull final Call<DirectItemSeenResponse> call,
|
||||||
@NonNull final Response<DirectItemSeenResponse> response) {
|
@NonNull final Response<DirectItemSeenResponse> response) {
|
||||||
if (!response.isSuccessful()) {
|
if (!response.isSuccessful()) {
|
||||||
handleErrorBody(call, response, null);
|
handleErrorBody(call, response, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final DirectItemSeenResponse seenResponse = response.body();
|
final DirectItemSeenResponse seenResponse = response.body();
|
||||||
if (seenResponse == null) return;
|
if (seenResponse == null) {
|
||||||
|
data.postValue(Resource.error(R.string.generic_null_response, null));
|
||||||
|
return;
|
||||||
|
}
|
||||||
inboxManager.fetchUnseenCount();
|
inboxManager.fetchUnseenCount();
|
||||||
final DirectItemSeenResponsePayload payload = seenResponse.getPayload();
|
final DirectItemSeenResponsePayload payload = seenResponse.getPayload();
|
||||||
if (payload == null) return;
|
if (payload == null) return;
|
||||||
@ -1822,14 +1825,17 @@ public final class ThreadManager {
|
|||||||
lastSeenAt.put(currentUser.getPk(), new DirectThreadLastSeenAt(timestamp, directItem.getItemId()));
|
lastSeenAt.put(currentUser.getPk(), new DirectThreadLastSeenAt(timestamp, directItem.getItemId()));
|
||||||
thread.setLastSeenAt(lastSeenAt);
|
thread.setLastSeenAt(lastSeenAt);
|
||||||
setThread(thread, true);
|
setThread(thread, true);
|
||||||
|
data.postValue(Resource.success(new Object()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(@NonNull final Call<DirectItemSeenResponse> call,
|
public void onFailure(@NonNull final Call<DirectItemSeenResponse> call,
|
||||||
@NonNull final Throwable t) {
|
@NonNull final Throwable t) {
|
||||||
Log.e(TAG, "onFailure: ", t);
|
Log.e(TAG, "onFailure: ", t);
|
||||||
|
data.postValue(Resource.error(t.getMessage(), null));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface OnSuccessAction {
|
private interface OnSuccessAction {
|
||||||
|
@ -45,6 +45,7 @@ public class DirectThread implements Serializable, Cloneable {
|
|||||||
private boolean approvalRequiredForNewMembers;
|
private boolean approvalRequiredForNewMembers;
|
||||||
private int inputMode;
|
private int inputMode;
|
||||||
private final List<ThreadContext> threadContextItems;
|
private final List<ThreadContext> threadContextItems;
|
||||||
|
private boolean isTemp;
|
||||||
|
|
||||||
public DirectThread(final String threadId,
|
public DirectThread(final String threadId,
|
||||||
final String threadV2Id,
|
final String threadV2Id,
|
||||||
@ -292,6 +293,14 @@ public class DirectThread implements Serializable, Cloneable {
|
|||||||
return threadContextItems;
|
return threadContextItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTemp() {
|
||||||
|
return isTemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTemp(final boolean isTemp) {
|
||||||
|
this.isTemp = isTemp;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public DirectItem getFirstDirectItem() {
|
public DirectItem getFirstDirectItem() {
|
||||||
DirectItem firstItem = null;
|
DirectItem firstItem = null;
|
||||||
|
@ -359,4 +359,16 @@ public final class Utils {
|
|||||||
}
|
}
|
||||||
return drawable;
|
return drawable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void enabledKeepScreenOn(@NonNull final Activity activity) {
|
||||||
|
final Window window = activity.getWindow();
|
||||||
|
if (window == null) return;
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void disableKeepScreenOn(@NonNull final Activity activity) {
|
||||||
|
final Window window = activity.getWindow();
|
||||||
|
if (window == null) return;
|
||||||
|
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,27 +2,25 @@ package awais.instagrabber.utils.emoji;
|
|||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.google.common.base.CharMatcher;
|
|
||||||
import com.google.common.base.Splitter;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.ibm.icu.impl.Utility;
|
import com.google.gson.Gson;
|
||||||
import com.ibm.icu.lang.CharSequences;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.ibm.icu.text.UnicodeSet;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import awais.instagrabber.customviews.emoji.Emoji;
|
import awais.instagrabber.customviews.emoji.Emoji;
|
||||||
import awais.instagrabber.customviews.emoji.EmojiCategory;
|
import awais.instagrabber.customviews.emoji.EmojiCategory;
|
||||||
import awais.instagrabber.customviews.emoji.EmojiCategoryType;
|
import awais.instagrabber.customviews.emoji.EmojiCategoryType;
|
||||||
|
import awais.instagrabber.utils.NetworkUtils;
|
||||||
|
|
||||||
public final class EmojiParser {
|
public final class EmojiParser {
|
||||||
private static final String TAG = EmojiParser.class.getSimpleName();
|
private static final String TAG = EmojiParser.class.getSimpleName();
|
||||||
@ -30,51 +28,8 @@ public final class EmojiParser {
|
|||||||
|
|
||||||
private static EmojiParser instance;
|
private static EmojiParser instance;
|
||||||
|
|
||||||
// private static final String COMBINING_ENCLOSING_KEYCAP = "\u20E3";
|
private Map<String, Emoji> allEmojis = Collections.emptyMap();
|
||||||
// private static final String ZWJ = "\u200D";
|
private Map<EmojiCategoryType, EmojiCategory> categoryMap = Collections.emptyMap();
|
||||||
// private static final UnicodeSet REGIONAL_INDICATORS = new UnicodeSet(0x1F1E6, 0x1F1FF).freeze();
|
|
||||||
// private static final UnicodeSet TAGS = new UnicodeSet(0xE0000, 0xE007F).freeze();
|
|
||||||
// private static final UnicodeSet FAMILY = new UnicodeSet("[\u200D 👦-👩 💋 ❤]").freeze();
|
|
||||||
// private static final UnicodeSet GENDER = new UnicodeSet().add(0x2640).add(0x2642).freeze();
|
|
||||||
// private static final UnicodeSet SPECIALS = new UnicodeSet("["
|
|
||||||
// + "{🐈⬛}{🐻❄}{👨🍼}{👩🍼}{🧑🍼}{🧑🎄}{🧑🤝🧑}{🏳🌈} {👁🗨} {🏴☠} {🐕🦺} {👨🦯} {👨🦼} {👨🦽} {👩🦯} {👩🦼} {👩🦽}"
|
|
||||||
// + "{🏳⚧}{🧑⚕}{🧑⚖}{🧑✈}{🧑🌾}{🧑🍳}{🧑🎓}{🧑🎤}{🧑🎨}{🧑🏫}{🧑🏭}{🧑💻}{🧑💼}{🧑🔧}{🧑🔬}{🧑🚀}{🧑🚒}{🧑🦯}{🧑🦼}{🧑🦽}"
|
|
||||||
// + "{❤🔥}, {❤🩹}, {😮💨}, {😵💫}" // #E13.1
|
|
||||||
// + "]").freeze();
|
|
||||||
// May have to add from above, if there is a failure in testAnnotationPaths. Failure will be like:
|
|
||||||
// got java.util.TreeSet<[//ldml/annotations/annotation[@cp="🏳⚧"][@type="tts"], //ldml/annotations/annotation[@cp="🧑⚕"][@type="tts"], ...
|
|
||||||
// just extract the items in "...", and change into {...} for adding above.
|
|
||||||
// Example: //ldml/annotations/annotation[@cp="🧑⚕"] ==> {🧑⚕}
|
|
||||||
// private static final UnicodeSet MAN_WOMAN = new UnicodeSet("[👨 👩]").freeze();
|
|
||||||
// private static final UnicodeSet OBJECT = new UnicodeSet("[👩 🎓 🌾 🍳 🏫 🏭 🎨 🚒 ✈ 🚀 🎤 💻 🔬 💼 🔧 ⚖ ⚕]").freeze();
|
|
||||||
// private static final String TYPE_TTS = "[@type=\"tts\"]";
|
|
||||||
private static final String EMOJI_VARIANT = "\uFE0F";
|
|
||||||
private static final UnicodeSet SKIN_TONE_MODIFIERS = new UnicodeSet("[🏻-🏿]").freeze();
|
|
||||||
private static final String SKIN_TONE_PATTERN = SKIN_TONE_MODIFIERS.toPattern(true);
|
|
||||||
private static final Map<EmojiCategoryType, EmojiCategory> CATEGORY_MAP = new LinkedHashMap<>();
|
|
||||||
private static final Map<String, Emoji> ALL_EMOJIS = new HashMap<>();
|
|
||||||
|
|
||||||
// private final UnicodeMap<String> emojiToMajorCategory = new UnicodeMap<>();
|
|
||||||
// private final UnicodeMap<String> emojiToMinorCategory = new UnicodeMap<>();
|
|
||||||
// private final UnicodeMap<String> toName = new UnicodeMap<>();
|
|
||||||
// /**
|
|
||||||
// * A mapping from a majorCategory to a unique ordering number, based on the first time it is encountered.
|
|
||||||
// */
|
|
||||||
// private final Map<String, Long> majorToOrder = new HashMap<>();
|
|
||||||
// private final List<String> majorToOrder = new LinkedList<String>();
|
|
||||||
// /**
|
|
||||||
// * A mapping from a minorCategory to a unique ordering number, based on the first time it is encountered.
|
|
||||||
// */
|
|
||||||
// private final Map<String, Long> minorToOrder = new HashMap<>();
|
|
||||||
// private final Map<String, Long> emojiToOrder = new LinkedHashMap<>();
|
|
||||||
// private final UnicodeSet nonConstructed = new UnicodeSet();
|
|
||||||
// private final UnicodeSet allRgi = new UnicodeSet();
|
|
||||||
// private final UnicodeSet allRgiNoES = new UnicodeSet();
|
|
||||||
// private final UnicodeMap<String> EXTRA_SYMBOL_MINOR_CATEGORIES = new UnicodeMap<>();
|
|
||||||
// private final Map<String, Long> EXTRA_SYMBOL_ORDER;
|
|
||||||
// private final boolean DEBUG = false;
|
|
||||||
// private Set<String> NAME_PATHS = null;
|
|
||||||
// private Set<String> KEYWORD_PATHS = null;
|
|
||||||
private ImmutableList<EmojiCategory> categories;
|
private ImmutableList<EmojiCategory> categories;
|
||||||
|
|
||||||
public static EmojiParser getInstance() {
|
public static EmojiParser getInstance() {
|
||||||
@ -89,267 +44,56 @@ public final class EmojiParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private EmojiParser() {
|
private EmojiParser() {
|
||||||
// Log.d(TAG, "Emoji: " + new Date());
|
final String file = "res/raw/emojis.json";
|
||||||
// String[][] data = {
|
|
||||||
// {"arrow", "→ ↓ ↑ ← ↔ ↕ ⇆ ⇅"},
|
|
||||||
// {"alphanum", "© ® ℗ ™ µ"},
|
|
||||||
// {"geometric", "▼ ▶ ▲ ◀ ● ○ ◯ ◊"},
|
|
||||||
// {"math", "× ÷ √ ∞ ∆ ∇ ⁻ ¹ ² ³ ≡ ∈ ⊂ ∩ ∪ ° + ± − = ≈ ≠ > < ≤ ≥ ¬ | ~"},
|
|
||||||
// {"punctuation", "§ † ‡ \\u0020 , 、 ، ; : ؛ ! ¡ ? ¿ ؟ ¶ ※ / \\ & # % ‰ ′ ″ ‴ @ * ♪ ♭ ♯ ` ´ ^ ¨ ‐ ― _ - – — • · . … 。 ‧ ・ ‘ ’ ‚ ' “ ” „ » « ( ) [ ] { } 〔 〕 〈 〉 《 》 「 」 『 』 〖 〗 【 】"},
|
|
||||||
// {"currency", "€ £ ¥ ₹ ₽ $ ¢ ฿ ₪ ₺ ₫ ₱ ₩ ₡ ₦ ₮ ৳ ₴ ₸ ₲ ₵ ៛ ₭ ֏ ₥ ₾ ₼ ₿ ؋"},
|
|
||||||
// {"other-symbol", "‾‽‸⁂↚↛↮↙↜↝↞↟↠↡↢↣↤↥↦↧↨↫↬↭↯↰↱↲↳↴↵↶↷↸↹↺↻↼↽↾↿⇀⇁⇂⇃⇄⇇⇈⇉⇊⇋⇌⇐⇍⇑⇒⇏⇓⇔⇎⇖⇗⇘⇙⇚⇛⇜⇝⇞⇟⇠⇡⇢⇣⇤⇥⇦⇧⇨⇩⇪⇵∀∂∃∅∉∋∎∏∑≮≯∓∕⁄∗∘∙∝∟∠∣∥∧∫∬∮∴∵∶∷∼∽∾≃≅≌≒≖≣≦≧≪≫≬≳≺≻⊁⊃⊆⊇⊕⊖⊗⊘⊙⊚⊛⊞⊟⊥⊮⊰⊱⋭⊶⊹⊿⋁⋂⋃⋅⋆⋈⋒⋘⋙⋮⋯⋰⋱■□▢▣▤▥▦▧▨▩▬▭▮▰△▴▵▷▸▹►▻▽▾▿◁◂◃◄◅◆◇◈◉◌◍◎◐◑◒◓◔◕◖◗◘◙◜◝◞◟◠◡◢◣◤◥◦◳◷◻◽◿⨧⨯⨼⩣⩽⪍⪚⪺₢₣₤₰₳₶₷₨﷼"},
|
|
||||||
// };
|
|
||||||
// get the maximum suborder for each subcategory
|
|
||||||
// Map<String, Long> subcategoryToMaxSuborder = new HashMap<>();
|
|
||||||
// for (String[] row : data) {
|
|
||||||
// final String subcategory = row[0];
|
|
||||||
// for (Entry<String, String> entry : emojiToMinorCategory.entrySet()) {
|
|
||||||
// if (entry.getValue().equals(subcategory)) {
|
|
||||||
// String emoji = entry.getKey();
|
|
||||||
// Long order = emojiToOrder.get(emoji);
|
|
||||||
// Long currentMax = subcategoryToMaxSuborder.get(subcategory);
|
|
||||||
// if (order == null) continue;
|
|
||||||
// if (currentMax == null || currentMax < order) {
|
|
||||||
// subcategoryToMaxSuborder.put(subcategory, order);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (DEBUG) System.out.println(subcategoryToMaxSuborder);
|
|
||||||
// Map<String, Long> _EXTRA_SYMBOL_ORDER = new LinkedHashMap<>();
|
|
||||||
// for (String[] row : data) {
|
|
||||||
// final String subcategory = row[0];
|
|
||||||
// final String characters = row[1];
|
|
||||||
//
|
|
||||||
// List<String> items = new ArrayList<>();
|
|
||||||
// for (int cp : With.codePointArray(characters)) {
|
|
||||||
// if (cp != ' ') {
|
|
||||||
// items.add(With.fromCodePoint(cp));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// final UnicodeSet uset = new UnicodeSet().addAll(items);
|
|
||||||
// if (uset.containsSome(EXTRA_SYMBOL_MINOR_CATEGORIES.keySet())) {
|
|
||||||
// throw new IllegalArgumentException("Duplicate values in " + EXTRA_SYMBOL_MINOR_CATEGORIES);
|
|
||||||
// }
|
|
||||||
// EXTRA_SYMBOL_MINOR_CATEGORIES.putAll(uset, subcategory);
|
|
||||||
// final Long countObject = subcategoryToMaxSuborder.get(subcategory);
|
|
||||||
// if (countObject == null) continue;
|
|
||||||
// long count = countObject;
|
|
||||||
// for (String s : items) {
|
|
||||||
// ++count;
|
|
||||||
// _EXTRA_SYMBOL_ORDER.put(s, count);
|
|
||||||
// }
|
|
||||||
// subcategoryToMaxSuborder.put(subcategory, count);
|
|
||||||
// }
|
|
||||||
// if (DEBUG) System.out.println(_EXTRA_SYMBOL_ORDER);
|
|
||||||
// EXTRA_SYMBOL_MINOR_CATEGORIES.freeze();
|
|
||||||
// EXTRA_SYMBOL_ORDER = ImmutableMap.copyOf(_EXTRA_SYMBOL_ORDER);
|
|
||||||
|
|
||||||
/*
|
|
||||||
# group: Smileys & People
|
|
||||||
# subgroup: face-positive
|
|
||||||
1F600 ; fully-qualified # 😀 grinning face
|
|
||||||
*/
|
|
||||||
final Splitter semi = Splitter.on(CharMatcher.anyOf(";#")).trimResults();
|
|
||||||
String majorCategory;
|
|
||||||
|
|
||||||
final String file = "res/raw/emoji_test.txt";
|
|
||||||
final ClassLoader classLoader = getClass().getClassLoader();
|
final ClassLoader classLoader = getClass().getClassLoader();
|
||||||
if (classLoader == null) {
|
if (classLoader == null) {
|
||||||
Log.e(TAG, "Emoji: classLoader is null");
|
Log.e(TAG, "Emoji: classLoader is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try (final InputStream in = classLoader.getResourceAsStream(file);
|
try (final InputStream in = classLoader.getResourceAsStream(file)) {
|
||||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
|
final String json = NetworkUtils.readFromInputStream(in);
|
||||||
String line;
|
final Gson gson = new Gson();
|
||||||
EmojiCategoryType categoryType = null;
|
final Type type = new TypeToken<Map<EmojiCategoryType, EmojiCategory>>() {}.getType();
|
||||||
while ((line = reader.readLine()) != null) {
|
categoryMap = gson.fromJson(json, type);
|
||||||
if (line.startsWith("#")) {
|
// Log.d(TAG, "EmojiParser: " + categoryMap);
|
||||||
line = line.substring(1).trim();
|
allEmojis = categoryMap.values()
|
||||||
if (line.startsWith("group:")) {
|
.stream()
|
||||||
majorCategory = line.substring("group:".length()).trim();
|
.flatMap((Function<EmojiCategory, Stream<Emoji>>) emojiCategory -> {
|
||||||
if (!majorCategory.equals("Component")) { // Skip Component
|
final Map<String, Emoji> emojis = emojiCategory.getEmojis();
|
||||||
if (majorCategory.equals("Smileys & Emotion") || majorCategory.equals("People & Body")) {
|
return emojis.values().stream();
|
||||||
// Put 'People & Body' in 'Smileys & Emotion' category
|
})
|
||||||
categoryType = EmojiCategoryType.SMILEYS_AND_EMOTION;
|
.flatMap(emoji -> ImmutableList.<Emoji>builder()
|
||||||
} else {
|
.add(emoji)
|
||||||
categoryType = EmojiCategoryType.valueOfName(majorCategory);
|
.addAll(emoji.getVariants())
|
||||||
}
|
.build()
|
||||||
final boolean contains = CATEGORY_MAP.containsKey(categoryType);
|
.stream())
|
||||||
if (!contains) {
|
.collect(Collectors.toMap(Emoji::getUnicode, Function.identity()));
|
||||||
CATEGORY_MAP.put(categoryType, new EmojiCategory(categoryType));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (categoryType == null) continue;
|
|
||||||
line = line.trim();
|
|
||||||
if (line.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final Iterator<String> it = semi.split(line).iterator();
|
|
||||||
String emojiHex = it.next();
|
|
||||||
String original = Utility.fromHex(emojiHex, 4, " ");
|
|
||||||
String status = it.next();
|
|
||||||
if (!status.startsWith("fully-qualified")) { // only use fully qualified
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final EmojiCategory emojiCategory = CATEGORY_MAP.get(categoryType);
|
|
||||||
final Map<String, Emoji> emojis = emojiCategory == null ? new LinkedHashMap<>() : emojiCategory.getEmojis();
|
|
||||||
String comment = it.next();
|
|
||||||
// The comment is now of the form: # 😁 E0.6 beaming face with smiling eyes
|
|
||||||
int spacePos = comment.indexOf(' ');
|
|
||||||
spacePos = comment.indexOf(' ', spacePos + 1); // get second space
|
|
||||||
final String name = comment.substring(spacePos + 1).trim();
|
|
||||||
final Emoji emoji = new Emoji(original, name);
|
|
||||||
ALL_EMOJIS.put(original, emoji);
|
|
||||||
String minimal = original.replace(EMOJI_VARIANT, "");
|
|
||||||
//noinspection deprecation
|
|
||||||
boolean singleton = CharSequences.getSingleCodePoint(minimal) != Integer.MAX_VALUE;
|
|
||||||
if (!singleton && SKIN_TONE_MODIFIERS.containsSome(minimal)) {
|
|
||||||
// skin tone variant
|
|
||||||
final String parent = minimal.replaceAll(SKIN_TONE_PATTERN, "");
|
|
||||||
final Emoji parentEmoji = emojis.get(parent);
|
|
||||||
if (parentEmoji != null) {
|
|
||||||
parentEmoji.addVariant(emoji);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
emojis.put(original, emoji);
|
|
||||||
// skip constructed values
|
|
||||||
// if (minimal.contains(COMBINING_ENCLOSING_KEYCAP)
|
|
||||||
// || REGIONAL_INDICATORS.containsSome(minimal)
|
|
||||||
// || TAGS.containsSome(minimal)
|
|
||||||
// || !singleton && MODIFIERS.containsSome(minimal)
|
|
||||||
// || !singleton && FAMILY.containsAll(minimal)) {
|
|
||||||
// // do nothing
|
|
||||||
// } else if (minimal.contains(ZWJ)) { // only do certain ZWJ sequences
|
|
||||||
// if (SPECIALS.contains(minimal)
|
|
||||||
// || GENDER.containsSome(minimal)
|
|
||||||
// || MAN_WOMAN.contains(minimal.codePointAt(0)) && OBJECT.contains(minimal.codePointBefore(minimal.length()))) {
|
|
||||||
// // nonConstructed.add(minimal);
|
|
||||||
// }
|
|
||||||
// } else if (!minimal.contains("🔟")) {
|
|
||||||
// // nonConstructed.add(minimal);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
// for (Entry<Pair<Integer,Integer>, String> entry : majorPlusMinorToEmoji.entries()) {
|
|
||||||
// String minimal = entry.getValue();
|
|
||||||
// emojiToOrder.put(minimal, emojiToOrder.size());
|
|
||||||
// }
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Emoji: ", e);
|
Log.e(TAG, "EmojiParser: ", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private static <K, V> void putUnique(Map<K, V> map, K key, V value) {
|
|
||||||
// V oldValue = map.put(key, value);
|
|
||||||
// if (oldValue != null) {
|
|
||||||
// throw new ICUException("Attempt to change value of " + map
|
|
||||||
// + " for " + key
|
|
||||||
// + " from " + oldValue
|
|
||||||
// + " to " + value
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
public Map<EmojiCategoryType, EmojiCategory> getCategoryMap() {
|
public Map<EmojiCategoryType, EmojiCategory> getCategoryMap() {
|
||||||
return CATEGORY_MAP;
|
return categoryMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<EmojiCategory> getEmojiCategories() {
|
public List<EmojiCategory> getEmojiCategories() {
|
||||||
if (categories == null) {
|
if (categories == null) {
|
||||||
final Collection<EmojiCategory> categoryCollection = CATEGORY_MAP.values();
|
final Collection<EmojiCategory> categoryCollection = categoryMap.values();
|
||||||
categories = ImmutableList.copyOf(categoryCollection);
|
categories = ImmutableList.copyOf(categoryCollection);
|
||||||
}
|
}
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Emoji> getAllEmojis() {
|
public Map<String, Emoji> getAllEmojis() {
|
||||||
return ALL_EMOJIS;
|
return allEmojis;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Emoji getEmoji(final String emoji) {
|
public Emoji getEmoji(final String emoji) {
|
||||||
if (emoji == null) {
|
if (emoji == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return ALL_EMOJIS.get(emoji);
|
return allEmojis.get(emoji);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public String getMinorCategory(String emoji) {
|
|
||||||
// String minorCat = emojiToMinorCategory.get(emoji);
|
|
||||||
// if (minorCat == null) {
|
|
||||||
// minorCat = EXTRA_SYMBOL_MINOR_CATEGORIES.get(emoji);
|
|
||||||
// if (minorCat == null) {
|
|
||||||
// throw new InternalCldrException("No minor category (aka subgroup) found for " + emoji
|
|
||||||
// + ". Update emoji-test.txt to latest, and setValue PathHeader.. functionMap.put(\"minor\", ...");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return minorCat;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public long getEmojiToOrder(String emoji) {
|
|
||||||
// Long result = emojiToOrder.get(emoji);
|
|
||||||
// if (result == null) {
|
|
||||||
// result = EXTRA_SYMBOL_ORDER.get(emoji);
|
|
||||||
// if (result == null) {
|
|
||||||
// throw new InternalCldrException("No Order found for " + emoji
|
|
||||||
// + ". Update emoji-test.txt to latest, and setValue PathHeader.. functionMap.put(\"minor\", ...");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public long getEmojiMinorOrder(String minor) {
|
|
||||||
// Long result = minorToOrder.get(minor);
|
|
||||||
// if (result == null) {
|
|
||||||
// throw new InternalCldrException("No minor category (aka subgroup) found for " + minor
|
|
||||||
// + ". Update emoji-test.txt to latest, and setValue PathHeader.. functionMap.put(\"minor\", ...");
|
|
||||||
// }
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public String getMajorCategory(String emoji) {
|
|
||||||
// String majorCat = emojiToMajorCategory.get(emoji);
|
|
||||||
// if (majorCat == null) {
|
|
||||||
// if (EXTRA_SYMBOL_MINOR_CATEGORIES.containsKey(emoji)) {
|
|
||||||
// majorCat = "Symbols";
|
|
||||||
// } else {
|
|
||||||
// throw new InternalCldrException("No minor category (aka subgroup) found for " + emoji
|
|
||||||
// + ". Update emoji-test.txt to latest, and setValue PathHeader.. functionMap.put(\"major\", ...");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return majorCat;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public Set<String> getMinorCategoriesWithExtras() {
|
|
||||||
// Set<String> result = new LinkedHashSet<>(emojiToMinorCategory.values());
|
|
||||||
// result.addAll(EXTRA_SYMBOL_MINOR_CATEGORIES.getAvailableValues());
|
|
||||||
// return ImmutableSet.copyOf(result);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public UnicodeSet getEmojiInMinorCategoriesWithExtras(String minorCategory) {
|
|
||||||
// return new UnicodeSet(emojiToMinorCategory.getSet(minorCategory))
|
|
||||||
// .addAll(EXTRA_SYMBOL_MINOR_CATEGORIES.getSet(minorCategory))
|
|
||||||
// .freeze();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public synchronized Set<String> getNamePaths() {
|
|
||||||
// return NAME_PATHS != null ? NAME_PATHS : (NAME_PATHS = buildPaths(TYPE_TTS));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public synchronized Set<String> getKeywordPaths() {
|
|
||||||
// return KEYWORD_PATHS != null ? KEYWORD_PATHS : (KEYWORD_PATHS = buildPaths(""));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private ImmutableSet<String> buildPaths(String suffix) {
|
|
||||||
// ImmutableSet.Builder<String> builder = ImmutableSet.builder();
|
|
||||||
// for (String s : getNonConstructed()) {
|
|
||||||
// String base = "//ldml/annotations/annotation[@cp=\"" + s + "\"]" + suffix;
|
|
||||||
// builder.add(base);
|
|
||||||
// }
|
|
||||||
// return builder.build();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
package awais.instagrabber.utils.emoji;
|
|
||||||
|
|
||||||
// © 2016 and later: Unicode, Inc. and others.
|
|
||||||
// License & terms of use: http://www.unicode.org/copyright.html#License
|
|
||||||
/*
|
|
||||||
*******************************************************************************
|
|
||||||
* Copyright (C) 2009-2012, International Business Machines Corporation and *
|
|
||||||
* others. All Rights Reserved. *
|
|
||||||
*******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author markdavis
|
|
||||||
*/
|
|
||||||
public class ImmutableEntry<K, V> implements Map.Entry<K, V> {
|
|
||||||
final K k;
|
|
||||||
final V v;
|
|
||||||
|
|
||||||
ImmutableEntry(K key, V value) {
|
|
||||||
k = key;
|
|
||||||
v = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public K getKey() {return k;}
|
|
||||||
|
|
||||||
public V getValue() {return v;}
|
|
||||||
|
|
||||||
public V setValue(V value) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
try {
|
|
||||||
Map.Entry e = (Map.Entry) o;
|
|
||||||
return UnicodeMap.areEqual(e.getKey(), k) && UnicodeMap.areEqual(e.getValue(), v);
|
|
||||||
} catch (ClassCastException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int hashCode() {
|
|
||||||
return ((k == null ? 0 : k.hashCode()) ^ (v == null ? 0 : v.hashCode()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return k + "=" + v;
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -45,7 +45,6 @@ public class DirectSettingsViewModel extends AndroidViewModel {
|
|||||||
|
|
||||||
public DirectSettingsViewModel(final Application application,
|
public DirectSettingsViewModel(final Application application,
|
||||||
@NonNull final String threadId,
|
@NonNull final String threadId,
|
||||||
final DirectThread backup,
|
|
||||||
final boolean pending,
|
final boolean pending,
|
||||||
@NonNull final User currentUser) {
|
@NonNull final User currentUser) {
|
||||||
super(application);
|
super(application);
|
||||||
@ -59,7 +58,7 @@ public class DirectSettingsViewModel extends AndroidViewModel {
|
|||||||
final ContentResolver contentResolver = application.getContentResolver();
|
final ContentResolver contentResolver = application.getContentResolver();
|
||||||
resources = getApplication().getResources();
|
resources = getApplication().getResources();
|
||||||
final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance();
|
final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance();
|
||||||
threadManager = messagesManager.getThreadManager(threadId, pending, backup, currentUser, contentResolver);
|
threadManager = messagesManager.getThreadManager(threadId, pending, currentUser, contentResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -23,6 +23,7 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
import awais.instagrabber.customviews.emoji.Emoji;
|
import awais.instagrabber.customviews.emoji.Emoji;
|
||||||
import awais.instagrabber.managers.DirectMessagesManager;
|
import awais.instagrabber.managers.DirectMessagesManager;
|
||||||
|
import awais.instagrabber.managers.InboxManager;
|
||||||
import awais.instagrabber.managers.ThreadManager;
|
import awais.instagrabber.managers.ThreadManager;
|
||||||
import awais.instagrabber.models.Resource;
|
import awais.instagrabber.models.Resource;
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
@ -57,7 +58,6 @@ public class DirectThreadViewModel extends AndroidViewModel {
|
|||||||
|
|
||||||
public DirectThreadViewModel(@NonNull final Application application,
|
public DirectThreadViewModel(@NonNull final Application application,
|
||||||
@NonNull final String threadId,
|
@NonNull final String threadId,
|
||||||
final DirectThread backup,
|
|
||||||
final boolean pending,
|
final boolean pending,
|
||||||
@NonNull final User currentUser) {
|
@NonNull final User currentUser) {
|
||||||
super(application);
|
super(application);
|
||||||
@ -74,7 +74,7 @@ public class DirectThreadViewModel extends AndroidViewModel {
|
|||||||
contentResolver = application.getContentResolver();
|
contentResolver = application.getContentResolver();
|
||||||
recordingsDir = DirectoryUtils.getOutputMediaDirectory(application, "Recordings");
|
recordingsDir = DirectoryUtils.getOutputMediaDirectory(application, "Recordings");
|
||||||
final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance();
|
final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance();
|
||||||
threadManager = messagesManager.getThreadManager(threadId, pending, backup, currentUser, contentResolver);
|
threadManager = messagesManager.getThreadManager(threadId, pending, currentUser, contentResolver);
|
||||||
threadManager.fetchPendingRequests();
|
threadManager.fetchPendingRequests();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,16 +278,24 @@ public class DirectThreadViewModel extends AndroidViewModel {
|
|||||||
return threadManager.declineRequest();
|
return threadManager.declineRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void markAsSeen() {
|
public LiveData<Resource<Object>> markAsSeen() {
|
||||||
if (currentUser == null) return;
|
if (currentUser == null) {
|
||||||
|
return getSuccessEventResObjectLiveData();
|
||||||
|
}
|
||||||
final DirectThread thread = getThread().getValue();
|
final DirectThread thread = getThread().getValue();
|
||||||
if (thread == null) return;
|
if (thread == null) {
|
||||||
|
return getSuccessEventResObjectLiveData();
|
||||||
|
}
|
||||||
final List<DirectItem> items = thread.getItems();
|
final List<DirectItem> items = thread.getItems();
|
||||||
if (items == null || items.isEmpty()) return;
|
if (items == null || items.isEmpty()) {
|
||||||
|
return getSuccessEventResObjectLiveData();
|
||||||
|
}
|
||||||
final Optional<DirectItem> itemOptional = items.stream()
|
final Optional<DirectItem> itemOptional = items.stream()
|
||||||
.filter(item -> item.getUserId() != currentUser.getPk())
|
.filter(item -> item.getUserId() != currentUser.getPk())
|
||||||
.findFirst();
|
.findFirst();
|
||||||
if (!itemOptional.isPresent()) return;
|
if (!itemOptional.isPresent()) {
|
||||||
|
return getSuccessEventResObjectLiveData();
|
||||||
|
}
|
||||||
final DirectItem directItem = itemOptional.get();
|
final DirectItem directItem = itemOptional.get();
|
||||||
final Map<Long, DirectThreadLastSeenAt> lastSeenAt = thread.getLastSeenAt();
|
final Map<Long, DirectThreadLastSeenAt> lastSeenAt = thread.getLastSeenAt();
|
||||||
if (lastSeenAt != null) {
|
if (lastSeenAt != null) {
|
||||||
@ -296,10 +304,29 @@ public class DirectThreadViewModel extends AndroidViewModel {
|
|||||||
if (seenAt != null
|
if (seenAt != null
|
||||||
&& (Objects.equals(seenAt.getItemId(), directItem.getItemId())
|
&& (Objects.equals(seenAt.getItemId(), directItem.getItemId())
|
||||||
|| Long.parseLong(seenAt.getTimestamp()) >= directItem.getTimestamp())) {
|
|| Long.parseLong(seenAt.getTimestamp()) >= directItem.getTimestamp())) {
|
||||||
return;
|
return getSuccessEventResObjectLiveData();
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {
|
||||||
|
return getSuccessEventResObjectLiveData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
threadManager.markAsSeen(directItem);
|
return threadManager.markAsSeen(directItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private MutableLiveData<Resource<Object>> getSuccessEventResObjectLiveData() {
|
||||||
|
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
||||||
|
data.postValue(Resource.success(new Object()));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteThreadIfRequired() {
|
||||||
|
final DirectThread thread = getThread().getValue();
|
||||||
|
if (thread == null) return;
|
||||||
|
if (thread.isTemp() && (thread.getItems() == null || thread.getItems().isEmpty())) {
|
||||||
|
final InboxManager inboxManager = DirectMessagesManager.getInstance().getInboxManager();
|
||||||
|
inboxManager.removeThread(threadId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,25 +7,21 @@ import androidx.lifecycle.ViewModel;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
|
||||||
import awais.instagrabber.viewmodels.DirectSettingsViewModel;
|
import awais.instagrabber.viewmodels.DirectSettingsViewModel;
|
||||||
|
|
||||||
public class DirectSettingsViewModelFactory implements ViewModelProvider.Factory {
|
public class DirectSettingsViewModelFactory implements ViewModelProvider.Factory {
|
||||||
|
|
||||||
private final Application application;
|
private final Application application;
|
||||||
private final String threadId;
|
private final String threadId;
|
||||||
private final DirectThread backup;
|
|
||||||
private final boolean pending;
|
private final boolean pending;
|
||||||
private final User currentUser;
|
private final User currentUser;
|
||||||
|
|
||||||
public DirectSettingsViewModelFactory(@NonNull final Application application,
|
public DirectSettingsViewModelFactory(@NonNull final Application application,
|
||||||
@NonNull final String threadId,
|
@NonNull final String threadId,
|
||||||
@NonNull final DirectThread backup,
|
|
||||||
final boolean pending,
|
final boolean pending,
|
||||||
@NonNull final User currentUser) {
|
@NonNull final User currentUser) {
|
||||||
this.application = application;
|
this.application = application;
|
||||||
this.threadId = threadId;
|
this.threadId = threadId;
|
||||||
this.backup = backup;
|
|
||||||
this.pending = pending;
|
this.pending = pending;
|
||||||
this.currentUser = currentUser;
|
this.currentUser = currentUser;
|
||||||
}
|
}
|
||||||
@ -34,6 +30,6 @@ public class DirectSettingsViewModelFactory implements ViewModelProvider.Factory
|
|||||||
@Override
|
@Override
|
||||||
public <T extends ViewModel> T create(@NonNull final Class<T> modelClass) {
|
public <T extends ViewModel> T create(@NonNull final Class<T> modelClass) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (T) new DirectSettingsViewModel(application, threadId, backup, pending, currentUser);
|
return (T) new DirectSettingsViewModel(application, threadId, pending, currentUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,25 +7,21 @@ import androidx.lifecycle.ViewModel;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
|
||||||
import awais.instagrabber.viewmodels.DirectThreadViewModel;
|
import awais.instagrabber.viewmodels.DirectThreadViewModel;
|
||||||
|
|
||||||
public class DirectThreadViewModelFactory implements ViewModelProvider.Factory {
|
public class DirectThreadViewModelFactory implements ViewModelProvider.Factory {
|
||||||
|
|
||||||
private final Application application;
|
private final Application application;
|
||||||
private final String threadId;
|
private final String threadId;
|
||||||
private final DirectThread backup;
|
|
||||||
private final boolean pending;
|
private final boolean pending;
|
||||||
private final User currentUser;
|
private final User currentUser;
|
||||||
|
|
||||||
public DirectThreadViewModelFactory(@NonNull final Application application,
|
public DirectThreadViewModelFactory(@NonNull final Application application,
|
||||||
@NonNull final String threadId,
|
@NonNull final String threadId,
|
||||||
final DirectThread backup,
|
|
||||||
final boolean pending,
|
final boolean pending,
|
||||||
@NonNull final User currentUser) {
|
@NonNull final User currentUser) {
|
||||||
this.application = application;
|
this.application = application;
|
||||||
this.threadId = threadId;
|
this.threadId = threadId;
|
||||||
this.backup = backup;
|
|
||||||
this.pending = pending;
|
this.pending = pending;
|
||||||
this.currentUser = currentUser;
|
this.currentUser = currentUser;
|
||||||
}
|
}
|
||||||
@ -34,6 +30,6 @@ public class DirectThreadViewModelFactory implements ViewModelProvider.Factory {
|
|||||||
@Override
|
@Override
|
||||||
public <T extends ViewModel> T create(@NonNull final Class<T> modelClass) {
|
public <T extends ViewModel> T create(@NonNull final Class<T> modelClass) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (T) new DirectThreadViewModel(application, threadId, backup, pending, currentUser);
|
return (T) new DirectThreadViewModel(application, threadId, pending, currentUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
app/src/main/res/drawable/barinsta_logo.png
Normal file
BIN
app/src/main/res/drawable/barinsta_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
10
app/src/main/res/drawable/launch_screen.xml
Normal file
10
app/src/main/res/drawable/launch_screen.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:opacity="opaque">
|
||||||
|
<item android:drawable="@color/grey_900" />
|
||||||
|
<item>
|
||||||
|
<bitmap
|
||||||
|
android:gravity="center"
|
||||||
|
android:src="@drawable/barinsta_logo" />
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
@ -257,7 +257,7 @@
|
|||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="250dp"
|
android:layout_height="250dp"
|
||||||
android:translationY="250dp"
|
android:translationY="250dp"
|
||||||
android:visibility="gone"
|
android:visibility="visible"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/mark_as_seen"
|
android:id="@+id/mark_as_seen"
|
||||||
android:icon="@drawable/ic_outline_views_24"
|
android:icon="@drawable/ic_check_all_24"
|
||||||
android:title="@string/mark_as_seen"
|
android:title="@string/mark_as_seen"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
<item
|
<item
|
||||||
|
@ -122,10 +122,6 @@
|
|||||||
android:name="pending"
|
android:name="pending"
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
app:argType="boolean" />
|
app:argType="boolean" />
|
||||||
<argument
|
|
||||||
android:name="backup"
|
|
||||||
app:nullable="true"
|
|
||||||
app:argType="awais.instagrabber.repositories.responses.directmessages.DirectThread" />
|
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_thread_to_settings"
|
android:id="@+id/action_thread_to_settings"
|
||||||
app:destination="@id/directMessagesSettingsFragment" />
|
app:destination="@id/directMessagesSettingsFragment" />
|
||||||
@ -156,11 +152,6 @@
|
|||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
app:argType="boolean" />
|
app:argType="boolean" />
|
||||||
|
|
||||||
<argument
|
|
||||||
android:name="backup"
|
|
||||||
app:nullable="true"
|
|
||||||
app:argType="awais.instagrabber.repositories.responses.directmessages.DirectThread" />
|
|
||||||
|
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_settings_to_inbox"
|
android:id="@+id/action_settings_to_inbox"
|
||||||
app:destination="@id/directMessagesInboxFragment"
|
app:destination="@id/directMessagesInboxFragment"
|
||||||
|
File diff suppressed because it is too large
Load Diff
1
app/src/main/res/raw/emojis.json
Normal file
1
app/src/main/res/raw/emojis.json
Normal file
File diff suppressed because one or more lines are too long
@ -471,4 +471,5 @@
|
|||||||
<string name="edit_keyword_filter">Edit keyword filters</string>
|
<string name="edit_keyword_filter">Edit keyword filters</string>
|
||||||
<string name="added_keywords">Added keyword: {0} to filter list</string>
|
<string name="added_keywords">Added keyword: {0} to filter list</string>
|
||||||
<string name="removed_keywords">Removed keyword: {0} from filter list</string>
|
<string name="removed_keywords">Removed keyword: {0} from filter list</string>
|
||||||
|
<string name="marked_as_seen">Marked as seen</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -140,4 +140,8 @@
|
|||||||
<item name="dmOutgoingBgColor">@color/deep_purple_400</item>
|
<item name="dmOutgoingBgColor">@color/deep_purple_400</item>
|
||||||
<item name="dmDateHeaderBgColor">@color/deep_purple_600</item>
|
<item name="dmDateHeaderBgColor">@color/deep_purple_600</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="AppTheme.Launcher" parent="AppTheme.Dark">
|
||||||
|
<item name="android:windowBackground">@drawable/launch_screen</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
@ -5,7 +5,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.1.2'
|
classpath 'com.android.tools.build:gradle:4.1.3'
|
||||||
def nav_version = "2.3.4"
|
def nav_version = "2.3.4"
|
||||||
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
|
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
|
||||||
}
|
}
|
||||||
|
6
renovate.json
Normal file
6
renovate.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"extends": [
|
||||||
|
"config:base"
|
||||||
|
],
|
||||||
|
"prConcurrentLimit": 5
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user