Add plugins info fragments

This commit is contained in:
Vitaliy 2020-10-12 21:32:10 +03:00
parent 65de824b55
commit 08d6e1390d
13 changed files with 857 additions and 223 deletions

View file

@ -1,186 +1,205 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/bg_color"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/bg_color"
android:orientation="vertical"
tools:context=".activities.PluginActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
<include layout="@layout/global_preference_toolbar" />
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context=".activities.PluginActivity">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/plugin_image_placeholder"
android:layout_width="360dp"
android:layout_height="144dp"
android:layout_gravity="center"
android:scaleType="center"
android:background="@color/osmand_orange"
osmand:srcCompat="@drawable/ic_extension_dark"
android:visibility="gone"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/plugin_image"
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/plugin_image_placeholder"
android:layout_width="360dp"
android:layout_height="144dp"
android:layout_gravity="center"
android:background="@color/osmand_orange"
android:scaleType="center"
android:visibility="gone"
osmand:srcCompat="@drawable/ic_extension_dark" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/plugin_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"
android:maxWidth="360dp"
android:maxHeight="200dp"
android:scaleType="fitCenter" />
</FrameLayout>
<FrameLayout
android:id="@+id/plugin_header"
android:layout_width="match_parent"
android:layout_height="66dp"
android:background="?attr/expandable_list_item_background"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding">
<net.osmand.plus.widgets.ButtonEx
android:id="@+id/plugin_settings"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|start"
android:layout_marginTop="9dp"
android:layout_marginBottom="9dp"
android:background="?attr/expandable_list_item_background"
android:drawablePadding="10dp"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:paddingStart="0dp"
android:paddingLeft="0dp"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:text="@string/shared_string_settings"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_sub_text_size"
osmand:textAllCapsCompat="true"
osmand:typeface="@string/font_roboto_medium" />
<FrameLayout
android:layout_width="139dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginTop="@dimen/content_padding"
android:layout_marginBottom="@dimen/content_padding">
<net.osmand.plus.widgets.SwitchEx
android:id="@+id/plugin_enable_disable"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/switch_ex_background"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:paddingStart="9.5dp"
android:paddingLeft="9.5dp"
android:paddingTop="8dp"
android:paddingEnd="9.5dp"
android:paddingRight="9.5dp"
android:paddingBottom="8dp"
android:textColor="?attr/switch_ex_text_color"
android:textOff="@string/shared_string_off"
android:textOn="@string/shared_string_on"
android:textSize="@dimen/default_sub_text_size"
osmand:textAllCapsCompat="true"
osmand:typeface="@string/font_roboto_medium" />
<net.osmand.plus.widgets.ButtonEx
android:id="@+id/plugin_get"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/get_button_background"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:paddingStart="9.5dp"
android:paddingLeft="9.5dp"
android:paddingTop="8dp"
android:paddingEnd="9.5dp"
android:paddingRight="9.5dp"
android:paddingBottom="8dp"
android:text="@string/get_plugin"
android:textColor="@color/color_white"
android:textSize="@dimen/default_sub_text_size"
android:visibility="gone"
osmand:textAllCapsCompat="true"
osmand:typeface="@string/font_roboto_medium" />
</FrameLayout>
</FrameLayout>
<LinearLayout
android:id="@+id/plugin_install_header"
android:layout_width="match_parent"
android:layout_height="66dp"
android:background="?attr/plugin_details_install_header_bg"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:visibility="gone"
tools:visibility="visible">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ic_world_globe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:background="@drawable/ic_world_globe_dark" />
<net.osmand.plus.widgets.TextViewEx
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:text="@string/plugin_install_needs_network"
android:textColor="?android:textColorSecondary"
osmand:typeface="@string/font_roboto_regular" />
</LinearLayout>
<net.osmand.plus.widgets.TextViewEx
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"
android:maxWidth="360dp"
android:maxHeight="200dp"
android:scaleType="fitCenter" />
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:text="@string/shared_string_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
osmand:textAllCapsCompat="true"
osmand:typeface="@string/font_roboto_medium" />
</FrameLayout>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/plugin_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="14dp"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="@string/lorem_ipsum" />
<FrameLayout
android:id="@+id/plugin_header"
android:layout_width="match_parent"
android:layout_height="66dp"
android:background="?attr/expandable_list_item_background"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingStart="@dimen/content_padding">
</LinearLayout>
<net.osmand.plus.widgets.ButtonEx
android:id="@+id/plugin_settings"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|start"
android:layout_marginBottom="9dp"
android:layout_marginTop="9dp"
android:background="?attr/expandable_list_item_background"
android:drawablePadding="10dp"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:paddingLeft="0dp"
android:paddingRight="@dimen/content_padding"
android:text="@string/shared_string_settings"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_sub_text_size"
osmand:textAllCapsCompat="true"
osmand:typeface="@string/font_roboto_medium"
android:paddingEnd="@dimen/content_padding"
android:paddingStart="0dp" />
</ScrollView>
<FrameLayout
android:layout_width="139dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginBottom="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding">
<net.osmand.plus.widgets.SwitchEx
android:id="@+id/plugin_enable_disable"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/switch_ex_background"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:paddingBottom="8dp"
android:paddingLeft="9.5dp"
android:paddingRight="9.5dp"
android:paddingTop="8dp"
android:textColor="?attr/switch_ex_text_color"
android:textOff="@string/shared_string_off"
android:textOn="@string/shared_string_on"
android:textSize="@dimen/default_sub_text_size"
osmand:textAllCapsCompat="true"
osmand:typeface="@string/font_roboto_medium"
android:paddingStart="9.5dp"
android:paddingEnd="9.5dp" />
<net.osmand.plus.widgets.ButtonEx
android:id="@+id/plugin_get"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/get_button_background"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:paddingBottom="8dp"
android:paddingLeft="9.5dp"
android:paddingRight="9.5dp"
android:paddingTop="8dp"
android:text="@string/get_plugin"
android:textColor="@color/color_white"
android:textSize="@dimen/default_sub_text_size"
android:visibility="gone"
osmand:textAllCapsCompat="true"
osmand:typeface="@string/font_roboto_medium"
android:paddingStart="9.5dp"
android:paddingEnd="9.5dp" />
</FrameLayout>
</FrameLayout>
<LinearLayout
android:id="@+id/plugin_install_header"
android:layout_width="match_parent"
android:layout_height="66dp"
android:background="?attr/plugin_details_install_header_bg"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:visibility="gone"
tools:visibility="visible"
android:paddingEnd="@dimen/content_padding"
android:paddingStart="@dimen/content_padding">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ic_world_globe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:background="@drawable/ic_world_globe_dark"/>
<net.osmand.plus.widgets.TextViewEx
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:text="@string/plugin_install_needs_network"
android:textColor="?android:textColorSecondary"
osmand:typeface="@string/font_roboto_regular"
android:paddingStart="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding" />
</LinearLayout>
<net.osmand.plus.widgets.TextViewEx
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding"
android:text="@string/shared_string_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
osmand:textAllCapsCompat="true"
osmand:typeface="@string/font_roboto_medium"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/plugin_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginTop="14dp"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="@string/lorem_ipsum"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginStart="@dimen/content_padding" />
</LinearLayout>
</ScrollView>
</LinearLayout>

View file

@ -1,14 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/bg_color"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/global_preference_toolbar" />
</com.google.android.material.appbar.AppBarLayout>
<ListView
android:id="@android:id/list"
android:id="@+id/plugins_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/plugins_list_item"/>
</LinearLayout>
android:dividerHeight="1dp"
android:drawSelectorOnTop="true" />
</LinearLayout>

View file

@ -52,6 +52,7 @@
android:ellipsize="end"
android:lines="2"
android:maxLines="2"
android:scrollbars="none"
android:text="@string/lorem_ipsum"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"

View file

@ -974,10 +974,8 @@ public class MapActivityActions implements DialogProvider {
@Override
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int pos, boolean isChecked, int[] viewCoordinates) {
app.logEvent("drawer_plugins_open");
Intent newIntent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization()
.getPluginsActivity());
newIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
mapActivity.startActivity(newIntent);
MapActivity.clearPrevActivityIntent();
PluginsFragment.showInstance(mapActivity.getSupportFragmentManager());
return true;
}
}).createItem());

View file

@ -0,0 +1,255 @@
package net.osmand.plus.activities;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.chooseplan.ChoosePlanDialogFragment;
import net.osmand.plus.dialogs.PluginInstalledBottomSheetDialog.PluginStateListener;
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
import net.osmand.plus.srtmplugin.SRTMPlugin;
import org.apache.commons.logging.Log;
public class PluginInfoFragment extends BaseOsmAndFragment implements PluginStateListener {
private static final Log log = PlatformUtil.getLog(PluginInfoFragment.class);
private static final String TAG = PluginInfoFragment.class.getName();
public static final String EXTRA_PLUGIN_ID = "plugin_id";
private OsmandPlugin plugin;
private OsmandApplication app;
private View mainView;
private boolean nightMode;
@Override
public int getStatusBarColorId() {
return nightMode ? R.color.status_bar_color_dark : R.color.status_bar_color_light;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentActivity activity = requireMyActivity();
activity.getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
public void handleOnBackPressed() {
dismiss();
}
});
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
app = requireMyApplication();
Bundle args = getArguments();
if (args == null || !args.containsKey(EXTRA_PLUGIN_ID)) {
log.error("Required extra '" + EXTRA_PLUGIN_ID + "' is missing");
return null;
}
String pluginId = args.getString(EXTRA_PLUGIN_ID);
if (pluginId == null) {
log.error("Extra '" + EXTRA_PLUGIN_ID + "' is null");
return null;
}
plugin = OsmandPlugin.getPlugin(pluginId);
if (plugin == null) {
log.error("Plugin '" + EXTRA_PLUGIN_ID + "' not found");
return null;
}
Context context = requireContext();
nightMode = !app.getSettings().isLightContent();
LayoutInflater themedInflater = UiUtilities.getInflater(context, nightMode);
mainView = themedInflater.inflate(R.layout.plugin, container, false);
AndroidUtils.addStatusBarPadding21v(context, mainView);
TextView toolbarTitle = mainView.findViewById(R.id.toolbar_title);
toolbarTitle.setText(plugin.getName());
ImageView closeButton = mainView.findViewById(R.id.close_button);
closeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Activity activity = getMyActivity();
if (activity != null) {
activity.onBackPressed();
}
}
});
UiUtilities.rotateImageByLayoutDirection(closeButton, AndroidUtils.getLayoutDirection(app));
Drawable pluginImage = plugin.getAssetResourceImage();
if (pluginImage != null) {
ImageView img = mainView.findViewById(R.id.plugin_image);
img.setImageDrawable(pluginImage);
} else {
mainView.findViewById(R.id.plugin_image_placeholder).setVisibility(View.VISIBLE);
}
TextView descriptionView = mainView.findViewById(R.id.plugin_description);
descriptionView.setText(plugin.getDescription());
int linkTextColorId = nightMode ? R.color.ctx_menu_bottom_view_url_color_dark : R.color.ctx_menu_bottom_view_url_color_light;
int linkTextColor = ContextCompat.getColor(context, linkTextColorId);
descriptionView.setLinkTextColor(linkTextColor);
descriptionView.setMovementMethod(LinkMovementMethod.getInstance());
AndroidUtils.removeLinkUnderline(descriptionView);
Button settingsButton = mainView.findViewById(R.id.plugin_settings);
settingsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
FragmentActivity activity = getActivity();
if (activity != null) {
SettingsScreenType settingsScreenType = plugin.getSettingsScreenType();
if (settingsScreenType != null) {
BaseSettingsFragment.showInstance(activity, settingsScreenType);
}
}
}
});
CompoundButton enableDisableButton = mainView.findViewById(R.id.plugin_enable_disable);
enableDisableButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (plugin.isActive() == isChecked) {
return;
}
boolean ok = OsmandPlugin.enablePlugin(getActivity(), app, plugin, isChecked);
if (!ok) {
return;
}
updateState();
}
});
Button getButton = mainView.findViewById(R.id.plugin_get);
getButton.setText(plugin.isPaid() ? R.string.get_plugin : R.string.shared_string_install);
getButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
if (plugin instanceof SRTMPlugin) {
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
if (fragmentManager != null) {
ChoosePlanDialogFragment.showHillshadeSrtmPluginInstance(fragmentManager);
}
} else {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(plugin.getInstallURL())));
}
} catch (Exception e) {
//ignored
}
}
});
updateState();
return mainView;
}
@Override
public void onResume() {
super.onResume();
OsmandPlugin.checkInstalledMarketPlugins(app, getActivity());
updateState();
}
private void updateState() {
CompoundButton enableDisableButton = mainView.findViewById(R.id.plugin_enable_disable);
Button getButton = mainView.findViewById(R.id.plugin_get);
Button settingsButton = mainView.findViewById(R.id.plugin_settings);
settingsButton.setCompoundDrawablesWithIntrinsicBounds(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_settings), null, null, null);
View installHeader = mainView.findViewById(R.id.plugin_install_header);
if (plugin.needsInstallation()) {
getButton.setVisibility(View.VISIBLE);
enableDisableButton.setVisibility(View.GONE);
settingsButton.setVisibility(View.GONE);
installHeader.setVisibility(View.VISIBLE);
View worldGlobeIcon = installHeader.findViewById(R.id.ic_world_globe);
Drawable worldGlobeDrawable = app.getUIUtilities().getThemedIcon(R.drawable.ic_world_globe_dark);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
worldGlobeIcon.setBackground(worldGlobeDrawable);
} else {
worldGlobeIcon.setBackgroundDrawable(worldGlobeDrawable);
}
} else {
getButton.setVisibility(View.GONE);
enableDisableButton.setVisibility(View.VISIBLE);
enableDisableButton.setChecked(plugin.isActive());
if (plugin.getSettingsScreenType() == null || !plugin.isActive()) {
settingsButton.setVisibility(View.GONE);
} else {
settingsButton.setVisibility(View.VISIBLE);
}
installHeader.setVisibility(View.GONE);
}
}
@Override
public void onPluginStateChanged(OsmandPlugin plugin) {
updateState();
}
public void dismiss() {
FragmentActivity activity = getActivity();
if (activity != null) {
try {
activity.getSupportFragmentManager().popBackStack(TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
} catch (Exception e) {
log.error(e);
}
}
}
public static boolean showInstance(FragmentManager fragmentManager, OsmandPlugin plugin) {
try {
Bundle args = new Bundle();
args.putString(EXTRA_PLUGIN_ID, plugin.getId());
PluginInfoFragment fragment = new PluginInfoFragment();
fragment.setArguments(args);
fragmentManager.beginTransaction()
.add(R.id.fragmentContainer, fragment, TAG)
.addToBackStack(TAG)
.commitAllowingStateLoss();
return true;
} catch (Exception e) {
return false;
}
}
}

View file

@ -0,0 +1,338 @@
package net.osmand.plus.activities;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.PopupMenu;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil;
import net.osmand.aidl.ConnectedApp;
import net.osmand.plus.CustomOsmandPlugin;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.dialogs.PluginInstalledBottomSheetDialog.PluginStateListener;
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
import org.apache.commons.logging.Log;
import java.util.ArrayList;
public class PluginsFragment extends BaseOsmAndFragment implements PluginStateListener {
private static final Log log = PlatformUtil.getLog(PluginsFragment.class);
public static final String TAG = PluginsFragment.class.getName();
public static final String OPEN_PLUGINS = "open_plugins";
private OsmandApplication app;
private PluginsListAdapter adapter;
private LayoutInflater themedInflater;
private boolean nightMode;
@Override
public int getStatusBarColorId() {
return nightMode ? R.color.status_bar_color_dark : R.color.status_bar_color_light;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentActivity activity = requireMyActivity();
activity.getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
public void handleOnBackPressed() {
FragmentActivity activity = getActivity();
if (activity instanceof MapActivity) {
dismissImmediate();
MapActivity mapActivity = (MapActivity) activity;
mapActivity.launchPrevActivityIntent();
}
}
});
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
app = requireMyApplication();
nightMode = !app.getSettings().isLightContent();
themedInflater = UiUtilities.getInflater(getContext(), nightMode);
View view = themedInflater.inflate(R.layout.plugins, container, false);
AndroidUtils.addStatusBarPadding21v(getContext(), view);
TextView toolbarTitle = view.findViewById(R.id.toolbar_title);
toolbarTitle.setText(R.string.plugins_screen);
ImageView closeButton = view.findViewById(R.id.close_button);
closeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Activity activity = getMyActivity();
if (activity != null) {
activity.onBackPressed();
}
}
});
UiUtilities.rotateImageByLayoutDirection(closeButton, AndroidUtils.getLayoutDirection(app));
adapter = new PluginsListAdapter(requireContext());
ListView listView = view.findViewById(R.id.plugins_list);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Object tag = view.getTag();
if (tag instanceof OsmandPlugin) {
FragmentActivity activity = getActivity();
if (activity != null) {
PluginInfoFragment.showInstance(activity.getSupportFragmentManager(), (OsmandPlugin) tag);
}
} else if (tag instanceof ConnectedApp) {
switchEnabled((ConnectedApp) tag);
}
}
});
return view;
}
@Override
public void onResume() {
super.onResume();
OsmandPlugin.checkInstalledMarketPlugins(app, getActivity());
adapter.notifyDataSetChanged();
}
private void enableDisablePlugin(OsmandPlugin plugin, boolean enable) {
if (OsmandPlugin.enablePlugin(getActivity(), app, plugin, enable)) {
adapter.notifyDataSetChanged();
}
}
private void switchEnabled(@NonNull ConnectedApp connectedApp) {
app.getAidlApi().switchEnabled(connectedApp);
adapter.notifyDataSetChanged();
}
@Override
public void onPluginStateChanged(OsmandPlugin plugin) {
adapter.notifyDataSetChanged();
}
protected class PluginsListAdapter extends ArrayAdapter<Object> {
PluginsListAdapter(Context context) {
super(context, R.layout.plugins_list_item, new ArrayList<>());
addAll(app.getAidlApi().getConnectedApps());
addAll(OsmandPlugin.getVisiblePlugins());
}
@NonNull
@Override
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
View view = convertView;
if (view == null) {
view = themedInflater.inflate(R.layout.plugins_list_item, parent, false);
}
Context context = view.getContext();
boolean active = false;
int logoContDescId = R.string.shared_string_disable;
String name = "";
ImageButton pluginLogo = view.findViewById(R.id.plugin_logo);
ImageView pluginOptions = view.findViewById(R.id.plugin_options);
TextView pluginDescription = view.findViewById(R.id.plugin_description);
Object item = getItem(position);
if (item instanceof ConnectedApp) {
final ConnectedApp app = (ConnectedApp) item;
active = app.isEnabled();
if (!active) {
logoContDescId = R.string.shared_string_enable;
}
name = app.getName();
pluginDescription.setText(R.string.third_party_application);
pluginLogo.setImageDrawable(app.getIcon());
pluginLogo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
switchEnabled(app);
}
});
pluginOptions.setVisibility(View.GONE);
pluginOptions.setOnClickListener(null);
view.setTag(app);
} else if (item instanceof OsmandPlugin) {
final OsmandPlugin plugin = (OsmandPlugin) item;
active = plugin.isActive();
if (!active) {
logoContDescId = plugin.needsInstallation()
? R.string.access_shared_string_not_installed : R.string.shared_string_enable;
}
name = plugin.getName();
pluginDescription.setText(plugin.getDescription());
int linkTextColorId = nightMode ? R.color.ctx_menu_bottom_view_url_color_dark : R.color.ctx_menu_bottom_view_url_color_light;
int linkTextColor = ContextCompat.getColor(context, linkTextColorId);
pluginDescription.setLinkTextColor(linkTextColor);
pluginDescription.setMovementMethod(LinkMovementMethod.getInstance());
AndroidUtils.removeLinkUnderline(pluginDescription);
int color = AndroidUtils.getColorFromAttr(context, R.attr.list_background_color);
pluginLogo.setImageDrawable(UiUtilities.tintDrawable(plugin.getLogoResource(), color));
pluginLogo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (plugin.isActive() || !plugin.needsInstallation()) {
enableDisablePlugin(plugin, !plugin.isActive());
}
}
});
pluginOptions.setVisibility(View.VISIBLE);
pluginOptions.setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_overflow_menu_white));
pluginOptions.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showOptionsMenu(v, plugin);
}
});
view.setTag(plugin);
}
pluginLogo.setContentDescription(getString(logoContDescId));
if (active) {
pluginLogo.setBackgroundResource(nightMode ? R.drawable.bg_plugin_logo_enabled_dark : R.drawable.bg_plugin_logo_enabled_light);
} else {
TypedArray attributes = context.getTheme().obtainStyledAttributes(new int[] {R.attr.bg_plugin_logo_disabled});
pluginLogo.setBackgroundDrawable(attributes.getDrawable(0));
attributes.recycle();
}
TextView pluginName = view.findViewById(R.id.plugin_name);
pluginName.setText(name);
pluginName.setContentDescription(name + " " + getString(active
? R.string.item_checked
: R.string.item_unchecked));
return view;
}
}
private void showOptionsMenu(View view, final OsmandPlugin plugin) {
final PopupMenu optionsMenu = new PopupMenu(view.getContext(), view);
if (plugin.isActive() || !plugin.needsInstallation()) {
MenuItem enableDisableItem = optionsMenu.getMenu().add(
plugin.isActive() ? R.string.shared_string_disable
: R.string.shared_string_enable);
enableDisableItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
enableDisablePlugin(plugin, !plugin.isActive());
optionsMenu.dismiss();
return true;
}
});
}
final SettingsScreenType settingsScreenType = plugin.getSettingsScreenType();
if (settingsScreenType != null && plugin.isActive()) {
MenuItem settingsItem = optionsMenu.getMenu().add(R.string.shared_string_settings);
settingsItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
FragmentActivity activity = getActivity();
if (activity != null) {
BaseSettingsFragment.showInstance(activity, settingsScreenType);
}
optionsMenu.dismiss();
return true;
}
});
}
if (plugin instanceof CustomOsmandPlugin) {
MenuItem settingsItem = optionsMenu.getMenu().add(R.string.shared_string_delete);
settingsItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
showDeletePluginDialog((CustomOsmandPlugin) plugin);
optionsMenu.dismiss();
return true;
}
});
}
optionsMenu.show();
}
private void showDeletePluginDialog(final CustomOsmandPlugin plugin) {
Context context = getContext();
if (context != null) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(getString(R.string.delete_confirmation_msg, plugin.getName()));
builder.setMessage(R.string.are_you_sure);
builder.setNegativeButton(R.string.shared_string_cancel, null);
builder.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
OsmandPlugin.removeCustomPlugin(app, plugin);
adapter.remove(plugin);
}
});
builder.show();
}
}
public void dismissImmediate() {
FragmentActivity activity = getActivity();
if (activity != null) {
try {
activity.getSupportFragmentManager().popBackStackImmediate(TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
} catch (Exception e) {
log.error(e);
}
}
}
public static boolean showInstance(FragmentManager fragmentManager) {
try {
PluginsFragment fragment = new PluginsFragment();
fragmentManager.beginTransaction()
.add(R.id.fragmentContainer, fragment, TAG)
.addToBackStack(TAG)
.commitAllowingStateLoss();
return true;
} catch (Exception e) {
return false;
}
}
}

View file

@ -77,15 +77,6 @@ public class SettingsActivity extends SettingsBaseActivity {
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if ((requestCode == PLUGINS_SELECTION_REQUEST) && (resultCode == PluginsActivity.ACTIVE_PLUGINS_LIST_MODIFIED)) {
finish();
startActivity(getIntent());
}
}
@Override
public boolean onPreferenceClick(Preference preference) {
if (preference == general) {

View file

@ -14,11 +14,13 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.activities.PluginActivity;
import net.osmand.plus.activities.PluginsFragment;
import net.osmand.plus.chooseplan.ChoosePlanDialogFragment;
import net.osmand.plus.dashboard.tools.DashFragmentData;
import net.osmand.plus.development.OsmandDevelopmentPlugin;
@ -84,7 +86,10 @@ public class DashPluginsFragment extends DashBaseFragment {
view.findViewById(R.id.show_all).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(getActivity(), getMyApplication().getAppCustomization().getPluginsActivity()));
FragmentActivity activity = getActivity();
if (activity != null) {
PluginsFragment.showInstance(activity.getSupportFragmentManager());
}
closeDashboard();
}
});

View file

@ -6,6 +6,7 @@ import android.content.Intent;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.MenuItem;
import android.view.View;
@ -25,6 +26,8 @@ import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.activities.LocalIndexHelper.LocalIndexType;
import net.osmand.plus.activities.LocalIndexInfo;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.PluginsFragment;
import net.osmand.plus.chooseplan.ChoosePlanDialogFragment;
import net.osmand.plus.download.CityItem;
import net.osmand.plus.download.CustomIndexItem;
@ -343,8 +346,7 @@ public class ItemViewHolder {
ChoosePlanDialogFragment.showSeaDepthMapsInstance(context.getSupportFragmentManager());
break;
case ASK_FOR_SEAMARKS_PLUGIN:
context.startActivity(new Intent(context, context.getMyApplication().getAppCustomization()
.getPluginsActivity()));
showPluginsScreen();
Toast.makeText(context.getApplicationContext(),
context.getString(R.string.activate_seamarks_plugin), Toast.LENGTH_SHORT).show();
break;
@ -352,8 +354,7 @@ public class ItemViewHolder {
ChoosePlanDialogFragment.showHillshadeSrtmPluginInstance(context.getSupportFragmentManager());
break;
case ASK_FOR_SRTM_PLUGIN_ENABLE:
context.startActivity(new Intent(context, context.getMyApplication().getAppCustomization()
.getPluginsActivity()));
showPluginsScreen();
Toast.makeText(context, context.getString(R.string.activate_srtm_plugin),
Toast.LENGTH_SHORT).show();
break;
@ -361,6 +362,13 @@ public class ItemViewHolder {
break;
}
}
private void showPluginsScreen() {
Bundle params = new Bundle();
params.putBoolean(PluginsFragment.OPEN_PLUGINS, true);
Intent intent = context.getIntent();
MapActivity.launchMapActivityMoveToTop(context, intent != null ? intent.getExtras() : null, null, params);
}
};
} else {
final boolean isDownloading = context.getDownloadThread().isDownloading(item);

View file

@ -11,16 +11,17 @@ import net.osmand.PlatformUtil;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.map.TileSourceManager;
import net.osmand.plus.MapMarkersHelper;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.PluginsFragment;
import net.osmand.plus.dashboard.DashboardOnMap.DashboardType;
import net.osmand.plus.mapmarkers.MapMarkersDialogFragment;
import net.osmand.plus.mapsource.EditMapSourceDialogFragment;
import net.osmand.plus.search.QuickSearchDialogFragment;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.MapMarkersHelper;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.dashboard.DashboardOnMap.DashboardType;
import net.osmand.plus.mapmarkers.MapMarkersDialogFragment;
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
import net.osmand.util.Algorithms;
@ -207,10 +208,22 @@ public class IntentHelper {
mapActivity.setIntent(null);
}
if (intent.hasExtra(BaseSettingsFragment.OPEN_SETTINGS)) {
String settingsType = intent.getStringExtra(BaseSettingsFragment.OPEN_SETTINGS);
String appMode = intent.getStringExtra(BaseSettingsFragment.APP_MODE_KEY);
if (BaseSettingsFragment.OPEN_CONFIG_PROFILE.equals(settingsType)) {
BaseSettingsFragment.showInstance(mapActivity, SettingsScreenType.CONFIGURE_PROFILE, ApplicationMode.valueOfStringKey(appMode, null));
String settingsTypeName = intent.getStringExtra(BaseSettingsFragment.OPEN_SETTINGS);
if (!Algorithms.isEmpty(settingsTypeName)) {
try {
SettingsScreenType screenType = SettingsScreenType.valueOf(settingsTypeName);
BaseSettingsFragment.showInstance(mapActivity, screenType, ApplicationMode.valueOfStringKey(appMode, null));
} catch (IllegalArgumentException e) {
LOG.error("error", e);
}
}
mapActivity.setIntent(null);
}
if (intent.hasExtra(PluginsFragment.OPEN_PLUGINS)) {
boolean openPlugins = intent.getBooleanExtra(PluginsFragment.OPEN_PLUGINS, false);
if (openPlugins) {
PluginsFragment.showInstance(mapActivity.getSupportFragmentManager());
}
mapActivity.setIntent(null);
}

View file

@ -22,6 +22,7 @@ import net.osmand.plus.activities.LocalIndexHelper;
import net.osmand.plus.activities.LocalIndexHelper.LocalIndexType;
import net.osmand.plus.activities.LocalIndexInfo;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.PluginsFragment;
import net.osmand.plus.download.DownloadActivityType;
import net.osmand.plus.download.DownloadIndexesThread;
import net.osmand.plus.download.DownloadValidationManager;
@ -110,8 +111,7 @@ public class MapDataMenuController extends MenuController {
activity.getString(R.string.activate_srtm_plugin), Toast.LENGTH_LONG).show();
}
} else {
activity.startActivity(new Intent(activity, activity.getMyApplication().getAppCustomization()
.getPluginsActivity()));
PluginsFragment.showInstance(activity.getSupportFragmentManager());
Toast.makeText(activity, activity.getString(R.string.activate_srtm_plugin),
Toast.LENGTH_SHORT).show();
}

View file

@ -27,12 +27,11 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.Version;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.PluginsActivity;
import net.osmand.plus.activities.SettingsActivity;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.download.DownloadActivity;
import net.osmand.plus.importfiles.ImportHelper;
import net.osmand.plus.helpers.WaypointHelper;
import net.osmand.plus.importfiles.ImportHelper;
import net.osmand.plus.myplaces.FavoritesActivity;
import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.views.OsmandMapTileView;
@ -184,10 +183,6 @@ public class OsmAndAppCustomization {
return DownloadActivity.class;
}
public Class<? extends Activity> getPluginsActivity() {
return PluginsActivity.class;
}
public Class<? extends Activity> getDownloadActivity() {
return DownloadActivity.class;
}

View file

@ -1,7 +1,6 @@
package net.osmand.plus.settings.fragments;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
@ -22,13 +21,13 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.OsmandApplication;
@ -36,14 +35,14 @@ import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.MapActivityActions;
import net.osmand.plus.activities.PluginsActivity;
import net.osmand.plus.activities.PluginsFragment;
import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.dialogs.ConfigureMapMenu;
import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.mapcontextmenu.MapContextMenu;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.widgets.style.CustomTypefaceSpan;
import org.apache.commons.logging.Log;
import java.util.ArrayList;
@ -229,8 +228,7 @@ public class ConfigureMenuRootFragment extends BaseOsmAndFragment {
if (holder instanceof DescriptionHolder) {
DescriptionHolder descriptionHolder = (DescriptionHolder) holder;
String plugins = getString(R.string.prefs_plugins);
setupClickableText(
descriptionHolder.description, (String) currentItem, plugins, new Intent(app, PluginsActivity.class));
setupClickableText(descriptionHolder.description, (String) currentItem, plugins);
descriptionHolder.image.setVisibility(View.GONE);
} else {
final ScreenType item = (ScreenType) currentItem;
@ -253,12 +251,15 @@ public class ConfigureMenuRootFragment extends BaseOsmAndFragment {
return items.size();
}
private void setupClickableText(TextView textView, String text, String clickableText, final Intent intent) {
private void setupClickableText(TextView textView, String text, String clickableText) {
SpannableString spannableString = new SpannableString(text);
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(@NonNull View view) {
startActivity(intent);
FragmentActivity activity = getActivity();
if (activity != null) {
PluginsFragment.showInstance(activity.getSupportFragmentManager());
}
}
};
try {