Update the glance section

This commit is contained in:
Tommaso Berlose 2020-10-14 01:41:43 +02:00
parent c5eb5358aa
commit c5fefb0e06
51 changed files with 186 additions and 88 deletions

View File

@ -29,6 +29,7 @@ import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
import com.tommasoberlose.anotherwidget.ui.activities.MusicPlayersFilterActivity
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import kotlinx.android.synthetic.main.glance_provider_settings_layout.view.*
import kotlinx.coroutines.*
class GlanceSettingsDialog(val context: Activity, val provider: Constants.GlanceProviderId, private val statusCallback: (() -> Unit)?) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
@ -77,7 +78,9 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
/* GOOGLE STEPS */
view.action_toggle_google_fit.isVisible = provider == Constants.GlanceProviderId.GOOGLE_FIT_STEPS
if (provider == Constants.GlanceProviderId.GOOGLE_FIT_STEPS) {
view.warning_container.isVisible = false
checkFitnessPermission(view)
checkGoogleFitConnection(view)
}
/* BATTERY INFO */
@ -111,48 +114,64 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
Constants.GlanceProviderId.GREETINGS -> Preferences.showGreetings
}
var job: Job? = null
view.provider_switch.setOnCheckedChangeListener { _, isChecked ->
when (provider) {
Constants.GlanceProviderId.PLAYING_SONG -> {
Preferences.showMusic = isChecked
checkNotificationPermission(view)
}
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
Preferences.showNextAlarm = isChecked
checkNextAlarm(view)
}
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
Preferences.showBatteryCharging = isChecked
}
Constants.GlanceProviderId.NOTIFICATIONS -> {
Preferences.showNotifications = isChecked
checkLastNotificationsPermission(view)
}
Constants.GlanceProviderId.GREETINGS -> {
Preferences.showGreetings = isChecked
}
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
if (isChecked) {
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
if (!GoogleSignIn.hasPermissions(account,
ActivityDetectionReceiver.FITNESS_OPTIONS
)) {
val mGoogleSignInClient = GoogleSignIn.getClient(context, GoogleSignInOptions.Builder(
GoogleSignInOptions.DEFAULT_SIGN_IN).addExtension(
ActivityDetectionReceiver.FITNESS_OPTIONS
).build())
context.startActivityForResult(mGoogleSignInClient.signInIntent, 2)
} else {
Preferences.showDailySteps = true
job?.cancel()
job = GlobalScope.launch(Dispatchers.IO) {
delay(300)
withContext(Dispatchers.Main) {
when (provider) {
Constants.GlanceProviderId.PLAYING_SONG -> {
Preferences.showMusic = isChecked
checkNotificationPermission(view)
}
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
Preferences.showNextAlarm = isChecked
checkNextAlarm(view)
}
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
Preferences.showBatteryCharging = isChecked
}
Constants.GlanceProviderId.NOTIFICATIONS -> {
Preferences.showNotifications = isChecked
checkLastNotificationsPermission(view)
}
Constants.GlanceProviderId.GREETINGS -> {
Preferences.showGreetings = isChecked
}
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
if (isChecked) {
val account: GoogleSignInAccount? =
GoogleSignIn.getLastSignedInAccount(context)
if (!GoogleSignIn.hasPermissions(account,
ActivityDetectionReceiver.FITNESS_OPTIONS
)
) {
val mGoogleSignInClient =
GoogleSignIn.getClient(context, GoogleSignInOptions.Builder(
GoogleSignInOptions.DEFAULT_SIGN_IN).addExtension(
ActivityDetectionReceiver.FITNESS_OPTIONS
).build())
context.startActivityForResult(mGoogleSignInClient.signInIntent,
2)
} else {
Preferences.showDailySteps = true
}
} else {
Preferences.showDailySteps = false
}
view.warning_container.isVisible = false
checkFitnessPermission(view)
checkGoogleFitConnection(view)
}
else -> {
}
} else {
Preferences.showDailySteps = false
}
checkFitnessPermission(view)
statusCallback?.invoke()
}
else -> {}
}
statusCallback?.invoke()
}
setContentView(view)
@ -180,7 +199,6 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
}
private fun checkNotificationPermission(view: View) {
Log.d("ciao", NotificationManagerCompat.getEnabledListenerPackages(context).toString())
when {
NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName) -> {
view.warning_container.isVisible = false
@ -223,7 +241,6 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || context.checkGrantedPermission(
Manifest.permission.ACTIVITY_RECOGNITION)
) {
view.warning_container.isVisible = false
if (Preferences.showDailySteps) {
ActivityDetectionReceiver.registerFence(context)
} else {
@ -238,11 +255,51 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
}
} else {
ActivityDetectionReceiver.unregisterFence(context)
view.warning_container.isVisible = false
}
statusCallback?.invoke()
}
private fun checkGoogleFitConnection(view: View) {
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
if (!GoogleSignIn.hasPermissions(account,
ActivityDetectionReceiver.FITNESS_OPTIONS
)) {
view.warning_container.isVisible = true
view.warning_title.text = context.getString(R.string.settings_request_fitness_access)
view.warning_container.setOnClickListener {
GoogleSignIn.requestPermissions(
context,
1,
account,
ActivityDetectionReceiver.FITNESS_OPTIONS)
}
view.action_connect_to_google_fit.isVisible = true
view.action_disconnect_to_google_fit.isVisible = false
view.action_connect_to_google_fit.setOnClickListener {
GoogleSignIn.requestPermissions(
context,
1,
account,
ActivityDetectionReceiver.FITNESS_OPTIONS)
}
view.action_disconnect_to_google_fit.setOnClickListener(null)
view.google_fit_status_label.text = context.getString(R.string.google_fit_account_not_connected)
} else {
view.action_connect_to_google_fit.isVisible = false
view.action_disconnect_to_google_fit.isVisible = true
view.action_connect_to_google_fit.setOnClickListener(null)
view.action_disconnect_to_google_fit.setOnClickListener {
GoogleSignIn.getClient(context, GoogleSignInOptions.Builder(
GoogleSignInOptions.DEFAULT_SIGN_IN).addExtension(
ActivityDetectionReceiver.FITNESS_OPTIONS
).build()).signOut().addOnCompleteListener {
show()
}
}
view.google_fit_status_label.text = context.getString(R.string.google_fit_account_connected)
}
}
private fun requireFitnessPermission(view: View) {
Dexter.withContext(context)
.withPermissions(

View File

@ -43,19 +43,19 @@ object GlanceProviderHelper {
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_show_next_alarm_title),
R.drawable.round_alarm
R.drawable.round_access_alarm
)
}
Constants.GlanceProviderId.PLAYING_SONG -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_show_music_title),
R.drawable.round_music_note
R.drawable.round_radio
)
}
Constants.GlanceProviderId.CUSTOM_INFO -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_custom_notes_title),
R.drawable.round_notes
R.drawable.round_sticky_note_2
)
}
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
@ -67,7 +67,7 @@ object GlanceProviderHelper {
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_daily_steps_title),
R.drawable.round_directions_walk
R.drawable.round_run_circle
)
}
Constants.GlanceProviderId.NOTIFICATIONS -> {

View File

@ -202,8 +202,9 @@ class GlanceTabFragment : Fragment() {
injector.visibility(R.id.info_icon, View.VISIBLE)
}
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || activity?.checkGrantedPermission(
Manifest.permission.ACTIVITY_RECOGNITION) == true
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
if (GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS) && (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || activity?.checkGrantedPermission(
Manifest.permission.ACTIVITY_RECOGNITION) == true)
) {
injector.text(R.id.label,
if (Preferences.showDailySteps) getString(R.string.settings_visible) else getString(
@ -361,14 +362,12 @@ class GlanceTabFragment : Fragment() {
1 -> {
if (resultCode == Activity.RESULT_OK) {
adapter.notifyItemRangeChanged(0, adapter.data.size)
if (dialog != null) {
dialog?.show()
}
} else {
Preferences.showDailySteps = false
if (dialog != null) {
dialog?.show()
}
}
if (dialog != null) {
dialog?.show()
}
}
2 -> {
@ -383,16 +382,14 @@ class GlanceTabFragment : Fragment() {
FITNESS_OPTIONS)
} else {
adapter.notifyItemRangeChanged(0, adapter.data.size)
if (dialog != null) {
dialog?.show()
}
}
} catch (e: ApiException) {
e.printStackTrace()
Preferences.showDailySteps = false
if (dialog != null) {
dialog?.show()
}
}
if (dialog != null) {
dialog?.show()
}
}
}
@ -410,5 +407,8 @@ class GlanceTabFragment : Fragment() {
override fun onResume() {
super.onResume()
adapter.notifyItemRangeChanged(0, adapter.data.size)
if (dialog != null) {
dialog?.show()
}
}
}

View File

@ -30,11 +30,8 @@ import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.BitmapHelper
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
import com.tommasoberlose.anotherwidget.helpers.*
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
import com.tommasoberlose.anotherwidget.helpers.WidgetHelper
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter
@ -360,12 +357,13 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
false
}
// Music error indicator
// Glance error indicator
tabs?.getTabAt(4)?.orCreateBadge?.apply {
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
badgeGravity = BadgeDrawable.TOP_END
}?.isVisible = ((Preferences.showMusic || Preferences.showNotifications) && !NotificationManagerCompat.getEnabledListenerPackages(requireContext()).contains(requireContext().packageName)) ||
(Preferences.showDailySteps && !(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || requireActivity().checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION)))
(Preferences.showDailySteps && !(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || requireActivity().checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION))) ||
(AlarmHelper.isAlarmProbablyWrong(requireContext()))
}
override fun onResume() {

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 938 B

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2C6.48,2 2,6.48 2,12c0,5.52 4.48,10 10,10s10,-4.48 10,-10C22,6.48 17.52,2 12,2zM13.5,6c0.55,0 1,0.45 1,1c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1C12.5,6.45 12.95,6 13.5,6zM15.41,11.91c-0.71,-0.2 -1.63,-0.74 -2.32,-1.66l-0.41,2.35l1.19,1.3C13.95,13.98 14,14.1 14,14.22v3.28c0,0.28 -0.22,0.5 -0.5,0.5h0c-0.28,0 -0.5,-0.22 -0.5,-0.5v-3.08l-1.11,-1.21l-0.43,2.15c-0.05,0.27 -0.32,0.45 -0.59,0.39l-2.78,-0.57c-0.27,-0.06 -0.45,-0.32 -0.39,-0.59v0c0.06,-0.27 0.32,-0.44 0.59,-0.39l2.29,0.47l0.96,-4.89L10,10.35v1.15c0,0.28 -0.22,0.5 -0.5,0.5h0C9.22,12 9,11.78 9,11.5V10c0,-0.21 0.13,-0.4 0.33,-0.47l2.95,-1.09c0.49,-0.18 1.02,0.04 1.25,0.51c0.65,1.35 1.55,1.85 2.1,2C15.85,11 16,11.18 16,11.4v0.04C16,11.75 15.71,11.99 15.41,11.91z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M19,3H4.99C3.89,3 3,3.9 3,5l0.01,14c0,1.1 0.89,2 1.99,2h10l6,-6V5C21,3.9 20.1,3 19,3zM8,8h8c0.55,0 1,0.45 1,1v0c0,0.55 -0.45,1 -1,1H8c-0.55,0 -1,-0.45 -1,-1v0C7,8.45 7.45,8 8,8zM11,14H8c-0.55,0 -1,-0.45 -1,-1v0c0,-0.55 0.45,-1 1,-1h3c0.55,0 1,0.45 1,1v0C12,13.55 11.55,14 11,14zM14,19.5V15c0,-0.55 0.45,-1 1,-1h4.5L14,19.5z"/>
</vector>

View File

@ -103,27 +103,28 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/small_clock_warning"
android:padding="10dp"
android:padding="8dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="24dp"
android:orientation="horizontal">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:padding="10dp"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:src="@drawable/outline_info_24"
app:tint="@color/colorSecondaryText"/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:textSize="14sp"
android:layout_marginTop="8dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="@string/glance_info"
android:textColor="@color/colorSecondaryText"
android:letterSpacing="0"
android:fontFamily="@font/google_sans"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textAppearance="@style/AnotherWidget.Settings.Subtitle"
app:textAllCaps="false" />
</LinearLayout>
</LinearLayout>

View File

@ -14,8 +14,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:gravity="center_vertical"
@ -25,15 +25,8 @@
android:layout_height="48dp"
android:padding="11dp"
android:id="@+id/icon"
android:visibility="gone"
android:src="@drawable/round_music_note"
app:tint="@color/colorPrimaryText"/>
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="11dp"
android:src="@drawable/round_drag"
app:tint="@color/colorPrimaryText"/>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
@ -56,18 +49,16 @@
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="10dp"
android:padding="11dp"
android:src="@drawable/round_error"
app:tint="@color/errorColorText"
android:id="@+id/error_icon"/>
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="10dp"
android:padding="11dp"
android:id="@+id/info_icon"
android:src="@drawable/round_arrow_circle_down"
android:rotation="-90"
android:alpha="0.8"
android:src="@drawable/round_drag_handle"
app:tint="@color/colorPrimaryText"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@ -7,7 +7,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="56dp"
android:paddingBottom="48dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
@ -220,7 +220,8 @@
android:id="@+id/action_toggle_google_fit"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:paddingRight="8dp"
@ -230,14 +231,34 @@
android:layout_height="wrap_content"
android:textSize="16sp"
style="@style/AnotherWidget.Settings.Title"
android:text="Google Fit"/>
android:text="@string/google_fit"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="@string/settings_music_players_filter_subtitle"
android:id="@+id/google_fit_status_label"
android:text="@string/google_fit_account_not_connected"
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.Button.TextButton"
app:backgroundTint="@color/colorAccent_op10"
android:textColor="@color/colorAccent"
android:text="@string/action_connect"
android:textAllCaps="false"
android:id="@+id/action_connect_to_google_fit" />
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:textColor="@color/colorSecondaryText"
android:visibility="gone"
app:strokeColor="@color/disabledButtonBackground"
android:text="@string/action_disconnect"
android:textAllCaps="false"
android:id="@+id/action_disconnect_to_google_fit" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -204,6 +204,11 @@
<string name="settings_show_next_alarm_app_title">Allarme impostato da %s</string>
<string name="settings_show_next_alarm_app_subtitle_wrong">La prossima sveglia sembra impostata da un\'app errata. Disinstalla l\'app che imposta allarmi errati.</string>
<string name="settings_show_next_alarm_app_subtitle_correct">La prossima sveglia sembra corretta.</string>
<string name="google_fit_account_connected">Account collegato</string>
<string name="google_fit_account_not_connected">Account non collegato</string>
<string name="google_fit">Google Fit</string>
<string name="action_connect">Collega</string>
<string name="action_disconnect">Scollega</string>
<!-- Settings -->
<string name="action_share">Condividi</string>

View File

@ -221,6 +221,11 @@
<string name="settings_show_notifications_subtitle">Take a quick view of the last notifications showed up on your device.</string>
<string name="settings_show_greetings_title">Greetings</string>
<string name="settings_show_greetings_subtitle">View some cool phrase when you don\'t expect it.</string>
<string name="google_fit_account_connected">Account connected</string>
<string name="google_fit_account_not_connected">Account not connected</string>
<string name="google_fit">Google Fit</string>
<string name="action_connect">Connect</string>
<string name="action_disconnect">Disconnect</string>
<!-- Settings -->
<string name="action_share">Share</string>